You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2013/10/16 01:44:46 UTC
svn commit: r1532597 [9/10] - in /subversion/branches/log-addressing: ./
build/ac-macros/ build/generator/ build/generator/templates/ build/win32/
contrib/client-side/emacs/ notes/ subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/a...
Modified: subversion/branches/log-addressing/subversion/svnserve/svnserve.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/svnserve/svnserve.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/svnserve/svnserve.c (original)
+++ subversion/branches/log-addressing/subversion/svnserve/svnserve.c Tue Oct 15 23:44:41 2013
@@ -54,6 +54,22 @@
#include "private/svn_dep_compat.h"
#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
+# if APR_VERSION_AT_LEAST(1,3,0)
+# include <apr_thread_pool.h>
+# define HAVE_THREADPOOLS 1
+# define THREAD_ERROR_MSG _("Can't push task")
+# else
+# define HAVE_THREADPOOLS 0
+# define THREAD_ERROR_MSG _("Can't create thread")
+# endif
+#else
+# define HAVE_THREADPOOLS 0
+#endif
#include "winservice.h"
@@ -62,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. */
@@ -102,6 +119,50 @@ enum run_mode {
#endif
+/* Parameters for the worker thread pool used in threaded mode. */
+
+/* Have at least this many worker threads (even if there are no requests
+ * to handle).
+ *
+ * A 0 value is legal but increases the latency for the next incoming
+ * request. Higher values may be useful for servers that experience short
+ * bursts of concurrent requests followed by longer idle periods.
+ */
+#define THREADPOOL_MIN_SIZE 1
+
+/* Maximum number of worker threads. If there are more concurrent requests
+ * than worker threads, the extra requests get queued.
+ *
+ * Since very slow connections will hog a full thread for a potentially
+ * long time before timing out, be sure to not set this limit too low.
+ *
+ * On the other hand, keep in mind that every thread will allocate up to
+ * 4MB of unused RAM in the APR allocator of its root pool. 32 bit servers
+ * must hence do with fewer threads.
+ */
+#if (APR_SIZEOF_VOIDP <= 4)
+#define THREADPOOL_MAX_SIZE 64
+#else
+#define THREADPOOL_MAX_SIZE 256
+#endif
+
+/* Number of microseconds that an unused thread remains in the pool before
+ * being terminated.
+ *
+ * Higher values are useful if clients frequently send small requests and
+ * you want to minimize the latency for those.
+ */
+#define THREADPOOL_THREAD_IDLE_LIMIT 1000000
+
+/* Number of client to server connections that may concurrently in the
+ * TCP 3-way handshake state, i.e. are in the process of being created.
+ *
+ * Larger values improve scalability with lots of small requests comming
+ * on over long latency networks.
+ *
+ * The OS may actually use a lower limit than specified here.
+ */
+#define ACCEPT_BACKLOG 128
#ifdef WIN32
static apr_os_sock_t winservice_svnserve_accept_socket = INVALID_SOCKET;
@@ -291,7 +352,6 @@ static const apr_getopt_option_t svnserv
{0, 0, 0, 0}
};
-
static void usage(const char *progname, apr_pool_t *pool)
{
if (!progname)
@@ -310,15 +370,21 @@ static void help(apr_pool_t *pool)
#ifdef WIN32
svn_error_clear(svn_cmdline_fputs(_("usage: svnserve [-d | -i | -t | -X "
"| --service] [options]\n"
+ "Subversion repository server.\n"
+ "Type 'svnserve --version' to see the "
+ "program version.\n"
"\n"
"Valid options:\n"),
- stdout, pool));
+ stdout, pool));
#else
svn_error_clear(svn_cmdline_fputs(_("usage: svnserve [-d | -i | -t | -X] "
"[options]\n"
+ "Subversion repository server.\n"
+ "Type 'svnserve --version' to see the "
+ "program version.\n"
"\n"
"Valid options:\n"),
- stdout, pool));
+ stdout, pool));
#endif
for (i = 0; svnserve__options[i].name && svnserve__options[i].optch; i++)
{
@@ -388,17 +454,20 @@ static apr_status_t redirect_stdout(void
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;
@@ -408,23 +477,75 @@ static void
release_shared_pool(struct shared_pool_t *shared)
{
if (svn_atomic_dec(&shared->count) == 0)
- svn_pool_destroy(shared->pool);
+ svn_root_pools__release_pool(shared->pool, shared->root_pools);
}
#endif
+/* Wrapper around serve() that takes a socket instead of a connection.
+ * This is to off-load work from the main thread in threaded and fork modes.
+ */
+static svn_error_t *
+serve_socket(apr_socket_t *usock,
+ serve_params_t *params,
+ apr_pool_t *pool)
+{
+ apr_status_t status;
+ svn_ra_svn_conn_t *conn;
+ svn_error_t *err;
+
+ /* Enable TCP keep-alives on the socket so we time out when
+ * the connection breaks due to network-layer problems.
+ * If the peer has dropped the connection due to a network partition
+ * or a crash, or if the peer no longer considers the connection
+ * valid because we are behind a NAT and our public IP has changed,
+ * it will respond to the keep-alive probe with a RST instead of an
+ * acknowledgment segment, which will cause svn to abort the session
+ * even while it is currently blocked waiting for data from the peer. */
+ status = apr_socket_opt_set(usock, APR_SO_KEEPALIVE, 1);
+ if (status)
+ {
+ /* It's not a fatal error if we cannot enable keep-alives. */
+ }
+
+ /* create the connection, configure ports etc. */
+ conn = svn_ra_svn_create_conn3(usock, NULL, NULL,
+ params->compression_level,
+ params->zero_copy_limit,
+ params->error_check_interval,
+ pool);
+
+ /* process the actual request and log errors */
+ err = serve(conn, params, pool);
+ if (err)
+ logger__log_error(params->logger, err, NULL,
+ get_client_info(conn, params, pool));
+
+ return svn_error_trace(err);
+}
+
/* "Arguments" passed from the main thread to the connection thread */
struct serve_thread_t {
- svn_ra_svn_conn_t *conn;
+ 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(d->conn, 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;
@@ -478,21 +599,22 @@ 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;
serve_params_t params;
const char *arg;
apr_status_t status;
- svn_ra_svn_conn_t *conn;
apr_proc_t proc;
#if APR_HAS_THREADS
+ shared_pool_t *shared_pool;
+ struct serve_thread_t *thread_data;
+#if HAVE_THREADPOOLS
+ apr_thread_pool_t *threads;
+#else
apr_threadattr_t *tattr;
apr_thread_t *tid;
- struct shared_pool_t *shared_pool;
-
- struct serve_thread_t *thread_data;
+#endif
#endif
enum connection_handling_mode handling_mode = CONNECTION_DEFAULT;
apr_uint16_t port = SVN_RA_SVN_PORT;
@@ -510,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)
@@ -543,7 +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.logger = NULL;
params.vhost = FALSE;
params.username_case = CASE_ASIS;
params.memory_cache_size = (apr_uint64_t)-1;
@@ -799,9 +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(logger__create(¶ms.logger, log_filename, pool));
if (params.tunnel_user && run_mode != run_mode_tunnel)
{
@@ -814,6 +935,9 @@ 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);
apr_pool_cleanup_register(pool, pool, apr_pool_cleanup_null,
redirect_stdout);
@@ -960,7 +1084,7 @@ int main(int argc, const char *argv[])
return svn_cmdline_handle_exit_error(err, pool, "svnserve: ");
}
- apr_socket_listen(sock, 7);
+ apr_socket_listen(sock, ACCEPT_BACKLOG);
#if APR_HAS_FORK
if (run_mode != run_mode_listen_once && !foreground)
@@ -1022,8 +1146,45 @@ int main(int argc, const char *argv[])
svn_cache_config_set(&settings);
}
+ /* 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)
+ {
+ /* create the thread pool */
+ status = apr_thread_pool_create(&threads,
+ THREADPOOL_MIN_SIZE,
+ THREADPOOL_MAX_SIZE,
+ pool);
+ if (status)
+ {
+ err = svn_error_wrap_apr (status, _("Can't create thread pool"));
+ return svn_cmdline_handle_exit_error(err, pool, "svnserve: ");
+ }
+
+ /* let idle threads linger for a while in case more requests are
+ coming in */
+ apr_thread_pool_idle_wait_set(threads, THREADPOOL_THREAD_IDLE_LIMIT);
+
+ /* don't queue requests unless we reached the worker thread limit */
+ apr_thread_pool_threshold_set(threads, 0);
+ }
+#endif
+
while (1)
{
+ apr_pool_t *socket_pool;
+
#ifdef WIN32
if (winservice_is_stopping())
return ERROR_SUCCESS;
@@ -1033,22 +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
- = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));
+ 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))
{
- svn_pool_destroy(connection_pool);
+ svn_root_pools__release_pool(socket_pool, socket_pools);
continue;
}
if (status)
@@ -1058,29 +1218,9 @@ int main(int argc, const char *argv[])
return svn_cmdline_handle_exit_error(err, pool, "svnserve: ");
}
- /* Enable TCP keep-alives on the socket so we time out when
- * the connection breaks due to network-layer problems.
- * If the peer has dropped the connection due to a network partition
- * or a crash, or if the peer no longer considers the connection
- * valid because we are behind a NAT and our public IP has changed,
- * it will respond to the keep-alive probe with a RST instead of an
- * acknowledgment segment, which will cause svn to abort the session
- * even while it is currently blocked waiting for data from the peer. */
- status = apr_socket_opt_set(usock, APR_SO_KEEPALIVE, 1);
- if (status)
- {
- /* It's not a fatal error if we cannot enable keep-alives. */
- }
-
- conn = svn_ra_svn_create_conn3(usock, NULL, NULL,
- params.compression_level,
- params.zero_copy_limit,
- params.error_check_interval,
- connection_pool);
-
if (run_mode == run_mode_listen_once)
{
- err = serve(conn, ¶ms, connection_pool);
+ err = serve_socket(usock, ¶ms, socket_pool);
if (err)
svn_handle_error2(err, stdout, FALSE, "svnserve: ");
@@ -1095,16 +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);
- err = serve(conn, ¶ms, connection_pool);
- log_error(err, params.log_file,
- svn_ra_svn_conn_remote_host(conn),
- NULL, NULL, /* user, repos */
- connection_pool);
- svn_error_clear(err);
+ svn_error_clear(serve_socket(usock, ¶ms, socket_pool));
apr_socket_close(usock);
exit(0);
}
@@ -1115,14 +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,
- svn_ra_svn_conn_remote_host(conn),
- NULL, NULL, /* user, repos */
- connection_pool);
+ logger__log_error(params.logger, err, NULL, NULL);
svn_error_clear(err);
apr_socket_close(usock);
}
- svn_pool_destroy(connection_pool);
+ svn_root_pools__release_pool(socket_pool, socket_pools);
#endif
break;
@@ -1131,8 +1263,17 @@ 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);
- status = apr_threadattr_create(&tattr, connection_pool);
+ shared_pool = attach_shared_pool(socket_pool, socket_pools);
+
+ thread_data = apr_palloc(socket_pool, sizeof(*thread_data));
+ thread_data->usock = usock;
+ thread_data->params = ¶ms;
+ thread_data->shared_pool = shared_pool;
+#if HAVE_THREADPOOLS
+ status = apr_thread_pool_push(threads, serve_thread, thread_data,
+ 0, NULL);
+#else
+ status = apr_threadattr_create(&tattr, socket_pool);
if (status)
{
err = svn_error_wrap_apr(status, _("Can't create threadattr"));
@@ -1148,15 +1289,12 @@ int main(int argc, const char *argv[])
svn_error_clear(err);
exit(1);
}
- thread_data = apr_palloc(connection_pool, sizeof(*thread_data));
- thread_data->conn = conn;
- thread_data->params = ¶ms;
- thread_data->shared_pool = shared_pool;
status = apr_thread_create(&tid, tattr, serve_thread, thread_data,
shared_pool->pool);
+#endif
if (status)
{
- err = svn_error_wrap_apr(status, _("Can't create thread"));
+ err = svn_error_wrap_apr(status, THREAD_ERROR_MSG);
svn_handle_error2(err, stderr, FALSE, "svnserve: ");
svn_error_clear(err);
exit(1);
@@ -1167,8 +1305,8 @@ int main(int argc, const char *argv[])
case connection_mode_single:
/* Serve one connection at a time. */
- svn_error_clear(serve(conn, ¶ms, connection_pool));
- svn_pool_destroy(connection_pool);
+ svn_error_clear(serve_socket(usock, ¶ms, socket_pool));
+ svn_root_pools__release_pool(socket_pool, socket_pools);
}
}
Modified: subversion/branches/log-addressing/subversion/svnsync/svnsync.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/svnsync/svnsync.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/svnsync/svnsync.c (original)
+++ subversion/branches/log-addressing/subversion/svnsync/svnsync.c Tue Oct 15 23:44:41 2013
@@ -1846,6 +1846,7 @@ help_cmd(apr_getopt_t *os, void *baton,
const char *header =
_("general usage: svnsync SUBCOMMAND DEST_URL [ARGS & OPTIONS ...]\n"
+ "Subversion repository replication tool.\n"
"Type 'svnsync help <subcommand>' for help on a specific subcommand.\n"
"Type 'svnsync --version' to see the program version and RA modules.\n"
"\n"
Modified: subversion/branches/log-addressing/subversion/svnversion/svnversion.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/svnversion/svnversion.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/svnversion/svnversion.c (original)
+++ subversion/branches/log-addressing/subversion/svnversion/svnversion.c Tue Oct 15 23:44:41 2013
@@ -57,7 +57,10 @@ help(const apr_getopt_option_t *options,
svn_error_clear
(svn_cmdline_fprintf
(stdout, pool,
- _("usage: svnversion [OPTIONS] [WC_PATH [TRAIL_URL]]\n\n"
+ _("usage: svnversion [OPTIONS] [WC_PATH [TRAIL_URL]]\n"
+ "Subversion working copy identification tool.\n"
+ "Type 'svnversion --version' to see the program version.\n"
+ "\n"
" Produce a compact version identifier for the working copy path\n"
" WC_PATH. TRAIL_URL is the trailing portion of the URL used to\n"
" determine if WC_PATH itself is switched (detection of switches\n"
Modified: subversion/branches/log-addressing/subversion/tests/cmdline/authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/authz_tests.py?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/authz_tests.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/authz_tests.py Tue Oct 15 23:44:41 2013
@@ -1551,6 +1551,44 @@ def log_diff_dontdothat(sbox):
'log', ddt_url,
'-c', 1, '--diff')
+@Issue(4422)
+@Skip(svntest.main.is_ra_type_file)
+def authz_file_external_to_authz(sbox):
+ "replace file external with authz node"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ repo_url = sbox.repo_url
+
+ write_authz_file(sbox, {"/": "* = rw"})
+ write_restrictive_svnserve_conf(sbox.repo_dir)
+
+ sbox.simple_propset('svn:externals', 'Z ' + repo_url + '/iota', '')
+
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.tweak('', status=' M')
+ expected_status.add({
+ 'Z' : Item(status=' ', wc_rev='1', switched='X'),
+ })
+ svntest.actions.run_and_verify_update(wc_dir,
+ None, None, expected_status)
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'cp', repo_url + '/A',
+ repo_url + '/Z',
+ '-m', 'Add Z')
+
+ write_authz_file(sbox, {"/": "* = rw", "/Z": "* = "})
+
+ expected_status.tweak(wc_rev=2)
+
+ # ### This used to assert with
+ # ### svn: E235000: In file 'update_editor.c' line 3043: assertion failed
+ # ### (status != svn_wc__db_status_normal)
+
+ svntest.actions.run_and_verify_update(wc_dir,
+ None, None, expected_status)
+
########################################################################
# Run the tests
@@ -1585,6 +1623,7 @@ test_list = [ None,
authz_svnserve_groups,
authz_del_from_subdir,
log_diff_dontdothat,
+ authz_file_external_to_authz,
]
serial_only = True
Modified: subversion/branches/log-addressing/subversion/tests/cmdline/checkout_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/checkout_tests.py?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/checkout_tests.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/checkout_tests.py Tue Oct 15 23:44:41 2013
@@ -1057,7 +1057,7 @@ def checkout_wc_from_drive(sbox):
svntest.main.safe_rmtree(sbox.wc_dir)
os.mkdir(sbox.wc_dir)
- # create a virtual drive to the working copy folder
+ # create a virtual drive to the repository folder
drive = find_the_next_available_drive_letter()
if drive is None:
raise svntest.Skip
@@ -1093,8 +1093,49 @@ def checkout_wc_from_drive(sbox):
})
svntest.actions.run_and_verify_checkout(repo_url, wc_dir,
expected_output, expected_wc,
- None, None, None, None,
- '--force')
+ None, None, None, None)
+
+ wc2_dir = sbox.add_wc_path('2')
+ expected_output = wc.State(wc2_dir, {
+ 'D' : Item(status='A '),
+ 'D/H' : Item(status='A '),
+ 'D/H/psi' : Item(status='A '),
+ 'D/H/chi' : Item(status='A '),
+ 'D/H/omega' : Item(status='A '),
+ 'D/G' : Item(status='A '),
+ 'D/G/tau' : Item(status='A '),
+ 'D/G/pi' : Item(status='A '),
+ 'D/G/rho' : Item(status='A '),
+ 'D/gamma' : Item(status='A '),
+ 'C' : Item(status='A '),
+ 'mu' : Item(status='A '),
+ 'B' : Item(status='A '),
+ 'B/E' : Item(status='A '),
+ 'B/E/alpha' : Item(status='A '),
+ 'B/E/beta' : Item(status='A '),
+ 'B/F' : Item(status='A '),
+ 'B/lambda' : Item(status='A '),
+ })
+ svntest.actions.run_and_verify_checkout(repo_url + '/A', wc2_dir,
+ expected_output, None,
+ None, None, None, None)
+
+ wc3_dir = sbox.add_wc_path('3')
+ expected_output = wc.State(wc3_dir, {
+ 'H' : Item(status='A '),
+ 'H/psi' : Item(status='A '),
+ 'H/chi' : Item(status='A '),
+ 'H/omega' : Item(status='A '),
+ 'G' : Item(status='A '),
+ 'G/tau' : Item(status='A '),
+ 'G/pi' : Item(status='A '),
+ 'G/rho' : Item(status='A '),
+ 'gamma' : Item(status='A '),
+ })
+
+ svntest.actions.run_and_verify_checkout(repo_url + '/A/D', wc3_dir,
+ expected_output, None,
+ None, None, None, None)
finally:
os.chdir(was_cwd)
Modified: subversion/branches/log-addressing/subversion/tests/cmdline/commit_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/commit_tests.py?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/commit_tests.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/commit_tests.py Tue Oct 15 23:44:41 2013
@@ -1250,7 +1250,7 @@ def commit_add_file_twice(sbox):
svntest.actions.run_and_verify_commit(wc_dir,
None,
None,
- "already exists",
+ "E160020: File.*already exists",
wc_dir)
#----------------------------------------------------------------------
Modified: subversion/branches/log-addressing/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/externals_tests.py?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/externals_tests.py Tue Oct 15 23:44:41 2013
@@ -3264,6 +3264,89 @@ def switch_parent_relative_file_external
svntest.actions.run_and_verify_svn(None, None, [],
'update', branch_wc)
+@Issue(4420)
+def file_external_unversioned_obstruction(sbox):
+ """file externals unversioned obstruction"""
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ expected_output = verify.RegexOutput('r2 committed .*')
+ svntest.actions.run_and_verify_svnmucc(None, expected_output, [],
+ '-U', sbox.repo_url, '-m', 'r2: set external',
+ 'propset', 'svn:externals', '^/A/mu mu-ext', 'A')
+
+ sbox.simple_append('A/mu-ext', 'unversioned obstruction')
+
+ # Update reports a tree-conflict but status doesn't show any such
+ # conflict. I'm no sure whether this is correct.
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A' : Item(status=' U'),
+ 'A/mu-ext' : Item(status=' ', treeconflict='A'),
+ })
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.add({
+ 'A/mu-ext' : Item('unversioned obstruction'),
+ })
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+ expected_status.add({
+ 'A/mu-ext' : Item(status='M ', wc_rev='2', switched='X'),
+ })
+ svntest.actions.run_and_verify_update(wc_dir,
+ expected_output, expected_disk,
+ expected_status)
+
+@Issue(4001)
+@XFail()
+def file_external_versioned_obstruction(sbox):
+ """file externals versioned obstruction"""
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ expected_output = verify.RegexOutput('r2 committed .*')
+ svntest.actions.run_and_verify_svnmucc(None, expected_output, [],
+ '-U', sbox.repo_url, '-m', 'r2: set external',
+ 'propset', 'svn:externals', '^/A/mu mu-ext', 'A')
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A' : Item(status=' U'),
+ 'A/mu-ext' : Item(status='A '),
+ })
+ expected_disk = svntest.main.greek_state.copy()
+ expected_disk.add({
+ 'A/mu-ext' : Item('This is the file \'mu\'.\n'),
+ })
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 2)
+ expected_status.add({
+ 'A/mu-ext' : Item(status=' ', wc_rev='2', switched='X'),
+ })
+ svntest.actions.run_and_verify_update(wc_dir,
+ expected_output, expected_disk,
+ expected_status)
+
+ # Update skips adding the versioned node because of the file
+ # external obstruction then when the external is deleted the
+ # versioned node is missing from disk and wc.db. Not really sure
+ # what should happen, perhaps a not-present node?
+ expected_output = verify.RegexOutput('r3 committed .*')
+ svntest.actions.run_and_verify_svnmucc(None, expected_output, [],
+ '-U', sbox.repo_url, '-m', 'r3: copy file',
+ 'cp', 'head', 'A/mu', 'A/mu-ext',
+ 'propdel', 'svn:externals', 'A')
+
+ expected_output = svntest.wc.State(wc_dir, {
+ 'A' : Item(status=' U'),
+ 'A/mu-ext' : Item(verb='Removed external', prev_verb='Skipped'),
+ })
+ expected_disk.tweak('A/mu-ext', content='This is the file \'mu\'.\n')
+ expected_status.tweak(wc_rev=3)
+ expected_status.tweak('A/mu-ext', switched=None)
+ svntest.actions.run_and_verify_update(wc_dir,
+ expected_output, expected_disk,
+ expected_status)
+
+
########################################################################
# Run the tests
@@ -3317,6 +3400,8 @@ test_list = [ None,
pinned_externals,
update_dir_external_shallow,
switch_parent_relative_file_external,
+ file_external_unversioned_obstruction,
+ file_external_versioned_obstruction,
]
if __name__ == '__main__':
Modified: subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests.py?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests.py Tue Oct 15 23:44:41 2013
@@ -90,13 +90,6 @@ rep_lines_res = [
# In 'svn --version --quiet', we print only the version
# number in a single line.
(re.compile(r'^\d+\.\d+\.\d+(-[a-zA-Z0-9]+)?$'), 'X.Y.Z\n'),
- # 'svn --help' has a line with the version number.
- # It can vary, for example:
- # "Subversion command-line client, version 1.1.0."
- # "Subversion command-line client, version 1.1.0-dev."
- (re.compile(r'Subversion command-line client, '
- 'version \d+\.\d+\.\d+(.|-[a-zA-Z0-9]+\.)$'),
- 'Subversion command-line client, version X.Y.Z.'),
]
# This is a trigger pattern that selects the secondary set of
Modified: subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests_data/svn--help_stdout Tue Oct 15 23:44:41 2013
@@ -1,5 +1,5 @@
usage: svn <subcommand> [options] [args]
-Subversion command-line client, version X.Y.Z.
+Subversion command-line client.
Type 'svn help <subcommand>' for help on a specific subcommand.
Type 'svn --version' to see the program version and RA modules
or 'svn --version --quiet' to see just the version number.
Modified: subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout Tue Oct 15 23:44:41 2013
@@ -95,6 +95,8 @@ Valid options:
--with-all-revprops : retrieve all revision properties
--with-no-revprops : retrieve no revision properties
--with-revprop ARG : retrieve revision property ARG
+ --auto-moves : attempt to interpret matching unique DEL+ADD
+ pairs as moves
--depth ARG : limit operation by depth ARG ('empty', 'files',
'immediates', or 'infinity')
--diff : produce diff output
Modified: subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/getopt_tests_data/svn_help_stdout Tue Oct 15 23:44:41 2013
@@ -1,5 +1,5 @@
usage: svn <subcommand> [options] [args]
-Subversion command-line client, version X.Y.Z.
+Subversion command-line client.
Type 'svn help <subcommand>' for help on a specific subcommand.
Type 'svn --version' to see the program version and RA modules
or 'svn --version --quiet' to see just the version number.
Modified: subversion/branches/log-addressing/subversion/tests/cmdline/log_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/log_tests.py?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/log_tests.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/log_tests.py Tue Oct 15 23:44:41 2013
@@ -2184,6 +2184,7 @@ def log_diff(sbox):
compare_diff_output(r9diff, log_chain[1]['diff_lines'])
compare_diff_output(r8diff, log_chain[2]['diff_lines'])
+@Skip(svntest.main.is_fs_type_fsx)
def log_xml_old(sbox):
"log --xml shows kind for old style repository"
Modified: subversion/branches/log-addressing/subversion/tests/cmdline/move_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/move_tests.py?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/move_tests.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/move_tests.py Tue Oct 15 23:44:41 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/log-addressing/subversion/tests/cmdline/revert_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/revert_tests.py?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/revert_tests.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/revert_tests.py Tue Oct 15 23:44:41 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/log-addressing/subversion/tests/cmdline/tree_conflict_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/tree_conflict_tests.py?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/tree_conflict_tests.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/tree_conflict_tests.py Tue Oct 15 23:44:41 2013
@@ -1455,6 +1455,67 @@ def update_dir_with_not_present(sbox):
run_and_verify_svn(None, None, [],
'ci', '-m', '', wc_dir)
+@XFail()
+def update_delete_mixed_rev(sbox):
+ "update that deletes mixed-rev"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ sbox.simple_move('A/B/E/alpha', 'A/B/E/alpha2')
+ sbox.simple_commit()
+ sbox.simple_update()
+ sbox.simple_rm('A/B')
+ sbox.simple_commit()
+ sbox.simple_update(revision=1)
+ sbox.simple_update(target='A/B/E', revision=2)
+ sbox.simple_mkdir('A/B/E2')
+
+ # Update raises a tree conflict on A/B due to local mod A/B/E2
+ expected_output = wc.State(wc_dir, {
+ 'A/B' : Item(status=' ', treeconflict='C'),
+ })
+ expected_disk = main.greek_state.copy()
+ expected_disk.add({
+ 'A/B/E2' : Item(),
+ 'A/B/E/alpha2' : Item(contents='This is the file \'alpha\'.\n'),
+ })
+ expected_disk.remove('A/B/E/alpha')
+ expected_status = get_virginal_state(wc_dir, 3)
+ expected_status.remove('A/B/E/alpha')
+ expected_status.add({
+ 'A/B/E2' : Item(status='A ', wc_rev='-'),
+ 'A/B/E/alpha2' : Item(status=' ', copied='+', wc_rev='-'),
+ })
+ expected_status.tweak('A/B',
+ status='A ', copied='+', treeconflict='C', wc_rev='-')
+ expected_status.tweak('A/B/F', 'A/B/E', 'A/B/E/beta', 'A/B/lambda',
+ copied='+', wc_rev='-')
+ run_and_verify_update(wc_dir,
+ expected_output, expected_disk, expected_status,
+ None, None, None, None, None, 1,
+ wc_dir)
+
+ # Resolving to working state should give a mixed-revision copy that
+ # gets committed as multiple copies
+ run_and_verify_resolved([sbox.ospath('A/B')], sbox.ospath('A/B'))
+ expected_output = wc.State(wc_dir, {
+ 'A/B' : Item(verb='Adding'),
+ 'A/B/E' : Item(verb='Replacing'),
+ 'A/B/E2' : Item(verb='Adding'),
+ })
+ expected_status.tweak('A/B', 'A/B/E', 'A/B/E2', 'A/B/F', 'A/B/E/alpha2',
+ 'A/B/E/beta', 'A/B/lambda',
+ status=' ', wc_rev=4, copied=None, treeconflict=None)
+ run_and_verify_commit(wc_dir,
+ expected_output, expected_status, None,
+ wc_dir)
+
+ expected_info = {
+ 'Name': 'alpha2',
+ 'Node Kind': 'file',
+ }
+ run_and_verify_info([expected_info], sbox.repo_url + '/A/B/E/alpha2')
+
#######################################################################
# Run the tests
@@ -1485,6 +1546,7 @@ test_list = [ None,
at_directory_external,
actual_only_node_behaviour,
update_dir_with_not_present,
+ update_delete_mixed_rev,
]
if __name__ == '__main__':
Modified: subversion/branches/log-addressing/subversion/tests/cmdline/upgrade_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/cmdline/upgrade_tests.py?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/cmdline/upgrade_tests.py (original)
+++ subversion/branches/log-addressing/subversion/tests/cmdline/upgrade_tests.py Tue Oct 15 23:44:41 2013
@@ -430,7 +430,10 @@ def basic_upgrade_1_0(sbox):
url = sbox.repo_url
- xml_entries_relocate(sbox.wc_dir, 'file:///1.0.0/repos', url)
+ # This is non-canonical by the rules of svn_uri_canonicalize, it gets
+ # written into the entries file and upgrade has to canonicalize.
+ non_canonical_url = url[:-1] + '%%%02x' % ord(url[-1])
+ xml_entries_relocate(sbox.wc_dir, 'file:///1.0.0/repos', non_canonical_url)
# Attempt to use the working copy, this should give an error
expected_stderr = wc_is_too_old_regex
Propchange: subversion/branches/log-addressing/subversion/tests/libsvn_fs_x/
------------------------------------------------------------------------------
Merged /subversion/trunk/subversion/tests/libsvn_fs_x:r1516632-1532579
Merged /subversion/branches/fsfs-improvements/subversion/tests/libsvn_fs_x:r1499981-1509278,1516645-1532583
Propchange: subversion/branches/log-addressing/subversion/tests/libsvn_fs_x/string-table-test.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/tests/libsvn_ra/ra-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/libsvn_ra/ra-test.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/libsvn_ra/ra-test.c (original)
+++ subversion/branches/log-addressing/subversion/tests/libsvn_ra/ra-test.c Tue Oct 15 23:44:41 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,91 @@ commit_changes(svn_ra_session_t *session
return SVN_NO_ERROR;
}
+static svn_boolean_t last_tunnel_check;
+static int tunnel_open_count;
+static void *check_tunnel_baton;
+static void *open_tunnel_context;
+
+static svn_boolean_t
+check_tunnel(void *tunnel_baton, const char *tunnel_name)
+{
+ if (tunnel_baton != check_tunnel_baton)
+ abort();
+ last_tunnel_check = (0 == strcmp(tunnel_name, "test"));
+ return last_tunnel_check;
+}
+
+static svn_error_t *
+open_tunnel(apr_file_t **request, apr_file_t **response,
+ void **tunnel_context, void *tunnel_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_TEST_ASSERT(tunnel_baton == check_tunnel_baton);
+
+ 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;
+ open_tunnel_context = *tunnel_context = &kind;
+ ++tunnel_open_count;
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+close_tunnel(void *tunnel_context, void *tunnel_baton,
+ const char *tunnel_name, const char *user,
+ const char *hostname, int port)
+{
+ SVN_TEST_ASSERT(tunnel_context == open_tunnel_context);
+ SVN_TEST_ASSERT(tunnel_baton == check_tunnel_baton);
+ --tunnel_open_count;
+ return SVN_NO_ERROR;
+}
+
+
+
+
/*-------------------------------------------------------------------*/
/** The tests **/
@@ -151,6 +242,87 @@ location_segments_test(const svn_test_op
}
+/* Test ra_svn tunnel callbacks. */
+
+static svn_error_t *
+check_tunnel_callback_test(const svn_test_opts_t *opts,
+ apr_pool_t *pool)
+{
+ svn_ra_callbacks2_t *cbtable;
+ svn_ra_session_t *session;
+ svn_error_t *err;
+
+ SVN_ERR(svn_ra_create_callbacks(&cbtable, pool));
+ cbtable->check_tunnel_func = check_tunnel;
+ cbtable->open_tunnel_func = open_tunnel;
+ cbtable->close_tunnel_func = close_tunnel;
+ cbtable->tunnel_baton = check_tunnel_baton = &cbtable;
+ 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));
+
+ last_tunnel_check = TRUE;
+ open_tunnel_context = NULL;
+ err = svn_ra_open4(&session, NULL, "svn+foo://localhost/no-repo",
+ NULL, cbtable, NULL, NULL, pool);
+ svn_error_clear(err);
+ SVN_TEST_ASSERT(err);
+ SVN_TEST_ASSERT(!last_tunnel_check);
+ return SVN_NO_ERROR;
+}
+
+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->check_tunnel_func = check_tunnel;
+ cbtable->open_tunnel_func = open_tunnel;
+ cbtable->close_tunnel_func = close_tunnel;
+ cbtable->tunnel_baton = check_tunnel_baton = &cbtable;
+ 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));
+
+ last_tunnel_check = FALSE;
+ open_tunnel_context = NULL;
+ 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(last_tunnel_check);
+ 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 +330,9 @@ 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(check_tunnel_callback_test,
+ "test ra_svn tunnel callback check"),
+ SVN_TEST_OPTS_PASS(tunel_callback_test,
+ "test ra_svn tunnel creation callbacks"),
SVN_TEST_NULL
};
Modified: subversion/branches/log-addressing/subversion/tests/libsvn_subr/dirent_uri-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/libsvn_subr/dirent_uri-test.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/libsvn_subr/dirent_uri-test.c (original)
+++ subversion/branches/log-addressing/subversion/tests/libsvn_subr/dirent_uri-test.c Tue Oct 15 23:44:41 2013
@@ -911,6 +911,9 @@ static const testcase_canonicalize_t uri
{ "file:///C:/temp/REPOS", "file:///C:/temp/REPOS" },
{ "file:///c:/", "file:///c:" },
#endif /* SVN_USE_DOS_PATHS */
+ /* Hostnames that look like non-canonical paths */
+ { "file://./foo", "file://./foo" },
+ { "http://./foo", "http://./foo" },
/* svn_uri_is_canonical() was a private function in the 1.6 API, and
has since taken a MAJOR change of direction, namely that only
absolute URLs are considered canonical uris now. */
Propchange: subversion/branches/log-addressing/subversion/tests/libsvn_subr/packed-data-test.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/tests/libsvn_subr/prefix-string-test.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: subversion/branches/log-addressing/subversion/tests/libsvn_subr/priority-queue-test.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: subversion/branches/log-addressing/subversion/tests/libsvn_subr/stream-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/libsvn_subr/stream-test.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/libsvn_subr/stream-test.c (original)
+++ subversion/branches/log-addressing/subversion/tests/libsvn_subr/stream-test.c Tue Oct 15 23:44:41 2013
@@ -727,6 +727,50 @@ test_stream_base64_2(apr_pool_t *pool)
return SVN_NO_ERROR;
}
+static svn_error_t *
+test_stringbuf_from_stream(apr_pool_t *pool)
+{
+ const char *test_cases[] =
+ {
+ "",
+ "x",
+ "this string is longer than the default 64 minimum block size used"
+ "by the function under test",
+ NULL
+ };
+
+ const char **test_case;
+ for (test_case = test_cases; *test_case; ++test_case)
+ {
+ svn_stringbuf_t *result1, *result2, *result3, *result4;
+ svn_stringbuf_t *original = svn_stringbuf_create(*test_case, pool);
+
+ svn_stream_t *stream1 = svn_stream_from_stringbuf(original, pool);
+ svn_stream_t *stream2 = svn_stream_from_stringbuf(original, pool);
+
+ SVN_ERR(svn_stringbuf_from_stream(&result1, stream1, 0, pool));
+ SVN_ERR(svn_stringbuf_from_stream(&result2, stream1, 0, pool));
+ SVN_ERR(svn_stringbuf_from_stream(&result3, stream2, original->len,
+ pool));
+ SVN_ERR(svn_stringbuf_from_stream(&result4, stream2, original->len,
+ pool));
+
+ /* C-string contents must match */
+ SVN_TEST_STRING_ASSERT(result1->data, original->data);
+ SVN_TEST_STRING_ASSERT(result2->data, "");
+ SVN_TEST_STRING_ASSERT(result3->data, original->data);
+ SVN_TEST_STRING_ASSERT(result4->data, "");
+
+ /* assumed length must match */
+ SVN_TEST_ASSERT(result1->len == original->len);
+ SVN_TEST_ASSERT(result2->len == 0);
+ SVN_TEST_ASSERT(result3->len == original->len);
+ SVN_TEST_ASSERT(result4->len == 0);
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* The test table. */
struct svn_test_descriptor_t test_funcs[] =
@@ -752,5 +796,7 @@ struct svn_test_descriptor_t test_funcs[
"test base64 encoding/decoding streams"),
SVN_TEST_PASS2(test_stream_base64_2,
"base64 decoding allocation problem"),
+ SVN_TEST_PASS2(test_stringbuf_from_stream,
+ "test svn_stringbuf_from_stream"),
SVN_TEST_NULL
};
Modified: subversion/branches/log-addressing/subversion/tests/libsvn_subr/string-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/libsvn_subr/string-test.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/libsvn_subr/string-test.c (original)
+++ subversion/branches/log-addressing/subversion/tests/libsvn_subr/string-test.c Tue Oct 15 23:44:41 2013
@@ -656,7 +656,7 @@ test_string_similarity(apr_pool_t *pool)
const char *stra;
const char *strb;
apr_size_t lcs;
- int score;
+ unsigned int score;
} tests[] =
{
#define SCORE(lcs, len) ((2000 * (lcs) + (len)/2) / (len))
Modified: subversion/branches/log-addressing/subversion/tests/libsvn_wc/op-depth-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/libsvn_wc/op-depth-test.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/libsvn_wc/op-depth-test.c (original)
+++ subversion/branches/log-addressing/subversion/tests/libsvn_wc/op-depth-test.c Tue Oct 15 23:44:41 2013
@@ -8207,6 +8207,391 @@ move_update_parent_replace(const svn_tes
return SVN_NO_ERROR;
}
+static svn_error_t *
+copy_mixed_rev_mods(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "copy_mixed_rev_mods", 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_mkdir(&b, "A/B/C"));
+ SVN_ERR(sbox_wc_commit(&b, ""));
+ SVN_ERR(sbox_wc_update(&b, "", 1));
+ SVN_ERR(sbox_wc_update(&b, "A/B", 2));
+ SVN_ERR(sbox_wc_delete(&b, "A/B"));
+ SVN_ERR(sbox_wc_mkdir(&b, "A/B"));
+
+ {
+ nodes_row_t nodes[] = {
+ {0, "", "normal", 1, ""},
+ {0, "A", "normal", 1, "A"},
+ {0, "A/B", "normal", 2, "A/B"},
+ {0, "A/B/C", "normal", 2, "A/B/C"},
+ {2, "A/B", "normal", NO_COPY_FROM},
+ {2, "A/B/C", "base-deleted", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ SVN_ERR(sbox_wc_copy(&b, "A", "X"));
+ {
+ nodes_row_t nodes[] = {
+ {1, "X", "normal", 1, "A"},
+ {1, "X/B", "not-present", 2, "A/B"},
+ {2, "X/B", "normal", NO_COPY_FROM},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "X", nodes));
+ }
+
+ SVN_ERR(sbox_wc_commit(&b, "X"));
+ {
+ nodes_row_t nodes[] = {
+ {0, "X", "normal", 3, "X"},
+ {0, "X/B", "normal", 3, "X/B"},
+ {0}
+ };
+ SVN_ERR(check_db_rows(&b, "X", nodes));
+ }
+
+ 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_delete_intermediate(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_delete_intermediate", 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},
+
+ {0},
+ };
+ 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 delete A */
+ SVN_ERR(sbox_wc_delete(&b, "A"));
+
+ /* 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},
+
+ {0},
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+move_revert_intermediate(const svn_test_opts_t *opts, apr_pool_t *pool)
+{
+ svn_test__sandbox_t b;
+
+ SVN_ERR(svn_test__sandbox_create(&b, "move_revert_intermediate", 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},
+
+ {0},
+ };
+ 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},
+
+ {0},
+ };
+ SVN_ERR(check_db_rows(&b, "", nodes));
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
/* ---------------------------------------------------------------------- */
/* The list of test functions */
@@ -8362,5 +8747,13 @@ struct svn_test_descriptor_t test_funcs[
"update with tree conflict (issue 4347)"),
SVN_TEST_OPTS_PASS(move_update_parent_replace,
"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_delete_intermediate,
+ "move more than once, delete intermediate"),
+ SVN_TEST_OPTS_XFAIL(move_revert_intermediate,
+ "move more than once, revert intermediate"),
SVN_TEST_NULL
};
Modified: subversion/branches/log-addressing/subversion/tests/libsvn_wc/wc-queries-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/subversion/tests/libsvn_wc/wc-queries-test.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/subversion/tests/libsvn_wc/wc-queries-test.c (original)
+++ subversion/branches/log-addressing/subversion/tests/libsvn_wc/wc-queries-test.c Tue Oct 15 23:44:41 2013
@@ -165,7 +165,7 @@ test_sqlite_version(apr_pool_t *scratch_
printf("DBG: Using Sqlite %s\n", sqlite3_version);
if (sqlite3_libversion_number() != SQLITE_VERSION_NUMBER)
- printf("DBG: Compiled against Sqlite %s", SQLITE_VERSION);
+ printf("DBG: Compiled against Sqlite %s\n", SQLITE_VERSION);
if (sqlite3_libversion_number() < SQLITE_VERSION_NUMBER)
return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
Modified: subversion/branches/log-addressing/tools/client-side/svn-bench/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/tools/client-side/svn-bench/cl.h?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/tools/client-side/svn-bench/cl.h (original)
+++ subversion/branches/log-addressing/tools/client-side/svn-bench/cl.h Tue Oct 15 23:44:41 2013
@@ -90,6 +90,7 @@ typedef struct svn_cl__opt_state_t
svn_boolean_t no_revprops; /* retrieve no revprops */
apr_hash_t *revprop_table; /* table of revision properties to get/set */
svn_boolean_t use_merge_history; /* use/display extra merge information */
+ svn_boolean_t auto_moves; /* interpret unique DEL/ADD pairs as moves */
svn_boolean_t trust_server_cert; /* trust server SSL certs that would
otherwise be rejected as "untrusted" */
} svn_cl__opt_state_t;
@@ -107,7 +108,8 @@ svn_opt_subcommand_t
svn_cl__help,
svn_cl__null_export,
svn_cl__null_list,
- svn_cl__null_log;
+ svn_cl__null_log,
+ svn_cl__null_info;
/* See definition in main.c for documentation. */
Modified: subversion/branches/log-addressing/tools/client-side/svn-bench/null-log-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/tools/client-side/svn-bench/null-log-cmd.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/tools/client-side/svn-bench/null-log-cmd.c (original)
+++ subversion/branches/log-addressing/tools/client-side/svn-bench/null-log-cmd.c Tue Oct 15 23:44:41 2013
@@ -140,6 +140,9 @@ svn_cl__null_log(apr_getopt_t *os,
apr_array_header_t *revprops;
svn_opt_revision_t target_peg_revision;
const char *target_path_or_url;
+ svn_move_behavior_t move_behavior = opt_state->auto_moves
+ ? svn_move_behavior_auto_moves
+ : svn_move_behavior_explicit_moves;
SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
opt_state->targets,
@@ -202,13 +205,14 @@ svn_cl__null_log(apr_getopt_t *os,
APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_DATE;
if (!opt_state->quiet)
APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_LOG;
- SVN_ERR(svn_client_log5(targets,
+ SVN_ERR(svn_client_log6(targets,
&target_peg_revision,
opt_state->revision_ranges,
opt_state->limit,
opt_state->verbose,
opt_state->stop_on_copy,
opt_state->use_merge_history,
+ move_behavior,
revprops,
log_entry_receiver,
&lb,
Modified: subversion/branches/log-addressing/tools/client-side/svn-bench/svn-bench.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/tools/client-side/svn-bench/svn-bench.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/tools/client-side/svn-bench/svn-bench.c (original)
+++ subversion/branches/log-addressing/tools/client-side/svn-bench/svn-bench.c Tue Oct 15 23:44:41 2013
@@ -66,7 +66,9 @@ typedef enum svn_cl__longopt_t {
opt_with_revprop,
opt_with_all_revprops,
opt_with_no_revprops,
- opt_trust_server_cert
+ opt_auto_moves,
+ opt_trust_server_cert,
+ opt_changelist
} svn_cl__longopt_t;
@@ -147,6 +149,10 @@ const apr_getopt_option_t svn_cl__option
N_("set revision property ARG in new revision\n"
" "
"using the name[=value] format")},
+ {"auto-moves", opt_auto_moves, 0,
+ N_("attempt to interpret matching unique DEL+ADD\n"
+ " "
+ "pairs as moves")},
{"use-merge-history", 'g', 0,
N_("use/display additional information from merge\n"
" "
@@ -255,10 +261,20 @@ const svn_opt_subcommand_desc2_t svn_cl_
" behavior, which can be useful for determining branchpoints.\n"),
{'r', 'q', 'v', 'g', 'c', opt_targets, opt_stop_on_copy,
'l', opt_with_all_revprops, opt_with_no_revprops, opt_with_revprop,
- 'x',},
+ opt_auto_moves, 'x',},
{{opt_with_revprop, N_("retrieve revision property ARG")},
{'c', N_("the change made in revision ARG")}} },
+ { "null-info", svn_cl__null_info, {0}, N_
+ ("Display information about a local or remote item.\n"
+ "usage: info [TARGET[@REV]...]\n"
+ "\n"
+ " Print information about each TARGET (default: '.').\n"
+ " TARGET may be either a working-copy path or URL. If specified, REV\n"
+ " determines in which revision the target is first looked up.\n"),
+ {'r', 'R', opt_depth, opt_targets, opt_changelist}
+ },
+
{ NULL, NULL, {0}, NULL, {0} }
};
@@ -534,6 +550,9 @@ sub_main(int argc, const char *argv[], a
TRUE, pool);
}
break;
+ case 'R':
+ opt_state.depth = svn_depth_infinity;
+ break;
case 'N':
descend = FALSE;
break;
@@ -618,6 +637,9 @@ sub_main(int argc, const char *argv[], a
case 'g':
opt_state.use_merge_history = TRUE;
break;
+ case opt_auto_moves:
+ opt_state.auto_moves = TRUE;
+ break;
default:
/* Hmmm. Perhaps this would be a good place to squirrel away
opts that commands like svn diff might need. Hmmm indeed. */
Modified: subversion/branches/log-addressing/tools/dev/fsfs-access-map.c
URL: http://svn.apache.org/viewvc/subversion/branches/log-addressing/tools/dev/fsfs-access-map.c?rev=1532597&r1=1532596&r2=1532597&view=diff
==============================================================================
--- subversion/branches/log-addressing/tools/dev/fsfs-access-map.c (original)
+++ subversion/branches/log-addressing/tools/dev/fsfs-access-map.c Tue Oct 15 23:44:41 2013
@@ -52,9 +52,15 @@ typedef struct file_stats_t
/* number of lseek calls to clusters not previously read */
apr_int64_t uncached_seek_count;
+ /* number of lseek counts not followed by a read */
+ apr_int64_t unnecessary_seeks;
+
/* number of read() calls */
apr_int64_t read_count;
+ /* number of read() calls that returned 0 bytes */
+ apr_int64_t empty_reads;
+
/* total number of bytes returned by those reads */
apr_int64_t read_size;
@@ -86,6 +92,8 @@ typedef struct handle_info_t
/* bytes read so far in the current series of reads started (default: 0) */
apr_int64_t last_read_size;
+ /* number of read() calls in this series */
+ apr_int64_t read_count;
} handle_info_t;
/* useful typedef */
@@ -139,6 +147,11 @@ store_read_info(handle_info_t *handle_in
++*count;
}
}
+ else if (handle_info->read_count == 0)
+ {
+ /* two consecutive seeks */
+ handle_info->file->unnecessary_seeks++;
+ }
}
/* Handle a open() call. Ensures that a file_info_t for the given NAME
@@ -231,9 +244,13 @@ read_file(int handle, apr_int64_t count)
{
/* known file handle -> expand current read sequence */
+ handle_info->read_count++;
handle_info->last_read_size += count;
handle_info->file->read_count++;
handle_info->file->read_size += count;
+
+ if (count == 0)
+ handle_info->file->empty_reads++;
}
}
@@ -253,6 +270,7 @@ seek_file(int handle, apr_int64_t locati
handle_info->last_read_size = 0;
handle_info->last_read_start = location;
+ handle_info->read_count = 0;
handle_info->file->seek_count++;
/* if we seek to a location that had not been read from before,
@@ -678,6 +696,8 @@ print_stats(apr_pool_t *pool)
apr_int64_t clusters_read = 0;
apr_int64_t unique_clusters_read = 0;
apr_int64_t uncached_seek_count = 0;
+ apr_int64_t unnecessary_seek_count = 0;
+ apr_int64_t empty_read_count = 0;
apr_hash_index_t *hi;
for (hi = apr_hash_first(pool, files); hi; hi = apr_hash_next(hi))
@@ -695,13 +715,17 @@ print_stats(apr_pool_t *pool)
clusters_read += file->clusters_read;
unique_clusters_read += file->unique_clusters_read;
uncached_seek_count += file->uncached_seek_count;
+ unnecessary_seek_count += file->unnecessary_seeks;
+ empty_read_count += file->empty_reads;
}
printf("%20s files\n", svn__i64toa_sep(apr_hash_count(files), ',', pool));
printf("%20s files opened\n", svn__i64toa_sep(open_count, ',', pool));
printf("%20s seeks\n", svn__i64toa_sep(seek_count, ',', pool));
+ printf("%20s unnecessary seeks\n", svn__i64toa_sep(unnecessary_seek_count, ',', pool));
printf("%20s uncached seeks\n", svn__i64toa_sep(uncached_seek_count, ',', pool));
printf("%20s reads\n", svn__i64toa_sep(read_count, ',', pool));
+ printf("%20s empty reads\n", svn__i64toa_sep(empty_read_count, ',', pool));
printf("%20s unique clusters read\n", svn__i64toa_sep(unique_clusters_read, ',', pool));
printf("%20s clusters read\n", svn__i64toa_sep(clusters_read, ',', pool));
printf("%20s bytes read\n", svn__i64toa_sep(read_size, ',', pool));
@@ -767,4 +791,4 @@ int main(int argc, const char *argv[])
apr_file_close(file);
return 0;
-}
\ No newline at end of file
+}