Index: subversion/mod_dav_svn/mirror.c
===================================================================
--- subversion/mod_dav_svn/mirror.c	(revision 1934733)
+++ subversion/mod_dav_svn/mirror.c	(working copy)
@@ -33,6 +33,51 @@
 #include "dav_svn.h"
 
 
+/* If request R carries a Destination header (as COPY and MOVE do), rewrite
+   it to target the master server instead of this slave.  MASTER_URI is the
+   SVNMasterURI configuration value (not URI-encoded).  This is the
+   request-side counterpart to the Location-header rewrite performed by
+   dav_svn__location_header_filter() (the two are conceptual inverses, though
+   they differ in how they juggle the encoded/decoded root). */
+static void
+proxy_request_fixup_destination(request_rec *r, const char *master_uri)
+{
+    const char *destination = apr_table_get(r->headers_in, "Destination");
+    apr_uri_t dest_uri;
+    const char *dest_path, *root_dir, *rel;
+
+    if (destination == NULL
+        || apr_uri_parse(r->pool, destination, &dest_uri) != APR_SUCCESS
+        || dest_uri.path == NULL) {
+        return;
+    }
+
+    /* apr_uri_parse() leaves dest_uri.path URI-encoded but
+       dav_svn__get_root_dir() is decoded; encode the root so the comparison
+       and the rebuilt header both stay in the encoded domain.  REL is then
+       already encoded and must not be re-encoded -- only master_uri is, just
+       as dav_svn__location_header_filter() encodes it on the way back. */
+    dest_path = svn_urlpath__canonicalize(dest_uri.path, r->pool);
+    root_dir = svn_path_uri_encode(dav_svn__get_root_dir(r), r->pool);
+    root_dir = svn_urlpath__canonicalize(root_dir, r->pool);
+
+    rel = svn_urlpath__skip_ancestor(root_dir, dest_path);
+    if (rel == NULL) {
+        /* The Destination isn't under this slave's location, so we have no
+           way to translate it to the master.  Leave it untouched (the master
+           will reject it) but log for diagnosability. */
+        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                      "Not rewriting Destination '%s': outside slave root '%s'",
+                      dest_path, root_dir);
+        return;
+    }
+
+    apr_table_set(r->headers_in, "Destination",
+                  apr_pstrcat(r->pool, svn_path_uri_encode(master_uri, r->pool),
+                              "/", rel, SVN_VA_NULL));
+}
+
+
 /* Tweak the request record R, and add the necessary filters, so that
    the request is ready to be proxied away.  MASTER_URI is the URI
    specified in the SVNMasterURI Apache configuration value.
@@ -60,6 +105,8 @@ static int proxy_request_fixup(request_rec *r,
                                                r->pool);
     r->handler = "proxy-server";
 
+    proxy_request_fixup_destination(r, master_uri);
+
     /* ### FIXME: Seems we could avoid adding some or all of these
            filters altogether when the root_dir (that is, the slave's
            location, relative to the server root) and path portion of
Index: subversion/tests/cmdline/dav-mirror-autocheck.sh
===================================================================
--- subversion/tests/cmdline/dav-mirror-autocheck.sh	(revision 1934733)
+++ subversion/tests/cmdline/dav-mirror-autocheck.sh	(working copy)
@@ -356,7 +356,7 @@ fi
 [ -r "$MOD_AUTHZ_SVN" ] \
   || fail "authz_svn_module not found, please use '--enable-shared --enable-dso --with-apxs' with your 'configure' script"
 
-export LD_LIBRARY_PATH="$ABS_BUILDDIR/subversion/libsvn_ra_neon/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_local/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_svn/.libs:$LD_LIBRARY_PATH"
+export LD_LIBRARY_PATH="$ABS_BUILDDIR/subversion/libsvn_ra_local/.libs:$ABS_BUILDDIR/subversion/libsvn_ra_svn/.libs:$LD_LIBRARY_PATH"
 
 MASTER_REPOS="${MASTER_REPOS:-"$HTTPD_ROOT/master_repos"}"
 SLAVE_REPOS="${SLAVE_REPOS:-"$HTTPD_ROOT/slave_repos"}"
@@ -366,13 +366,13 @@ SLAVE_HOST=127.0.0.1
 #TEST_PORT=11111
 TEST_PORT=$(($RANDOM+1024))
 
-# location directive elements for master,slave,sync
-# tests currently work if master==slave,fail if different
-# ** Should different locations for each work?
-#MASTER_LOCATION="master"
-#SLAVE_LOCATION="slave"
-MASTER_LOCATION="repo"
-SLAVE_LOCATION="repo"
+# Location directive elements for master, slave, and sync.  Master and slave
+# deliberately use *different* locations so the proxy actually has to translate
+# paths (slave root_dir <-> master URI) on the way through; with matching
+# locations almost none of the rewrite logic -- including the COPY/MOVE
+# Destination fixup -- is exercised.
+MASTER_LOCATION="master"
+SLAVE_LOCATION="slave"
 SYNC_LOCATION="sync"
 
 MASTER_URL="http://${MASTER_HOST}:${TEST_PORT}/${MASTER_LOCATION}"
@@ -475,27 +475,28 @@ fi
 
 say "PASS: master, slave are both at r4, as expected"
 
-# The following test case is for the regression issue triggered by r917523.
-# The revision r917523 do some url encodings to the paths and uris which are
-# not url-encoded. But there is one additional url-encoding of an uri which is
-# already encoded. With this extra encoding, committing a path to slave which
-# has space in it fails. Please see this thread
-# http://svn.haxx.se/dev/archive-2011-03/0641.shtml for more info.
+# Encoding regression coverage (originally r917523, see
+# http://svn.haxx.se/dev/archive-2011-03/0641.shtml).  A path containing a
+# space must survive the proxy's URI rewriting encoded *exactly once*: the
+# COPY below sends a Destination header that proxy_request_fixup_destination()
+# must translate from the slave location to the master URI without re-encoding
+# the already-encoded "%20" (the bug double-encoded it to "%2520", silently
+# creating a path literally named "branch%20new").  The follow-up PUT
+# exercises the same encoding in the request-body location filter.
+say "Test case for encoding of paths with a space (regression r917523)"
 
-say "Test case for regression issue triggered by r917523"
-
-$svnmucc cp 2 "$BASE_URL/trunk" "$BASE_URL/branch new"
+$svnmucc cp 2 "$BASE_URL/trunk" "$BASE_URL/branch new" \
+  || fail "COPY to a path with a space failed (Destination mis-encoded?)"
 $svnmucc put /dev/null "$BASE_URL/branch new/file" \
---config-option servers:global:http-library=neon
-RETVAL=$?
+  || fail "PUT under a path with a space failed (request body mis-encoded?)"
 
-if [ $RETVAL -eq 0 ] ; then
-  say "PASS: committing a path which has space in it passes"
-else
-  say "FAIL: committing a path which has space in it fails as there are extra
-  url-encodings happening in server side"
-fi
+# A successful commit isn't enough: a double-encoded Destination still commits,
+# but lands as "branch%20new" on the master.  Assert the decoded name instead.
+$SVNLOOK tree --full-paths "$MASTER_REPOS" | grep -Fq "branch new/" \
+  || fail "path with a space was double-encoded by the proxy (expected 'branch new', got '%20'-escaped name on master)"
 
+say "PASS: committing a path which has a space in it passes"
+
 # Test case for commit to out-dated(though target path is up to date) slave.
 # See issue #3860 for details.
 say "Test case for out-dated slave commit"
@@ -521,14 +522,10 @@ say "Now the slave is at r$SLAVE_HEAD and master i
 
 # Now any other commit operation will fail with an out-of-date error
 
-$svn cp -m "Creating a branch" ^/trunk ^/branch/newbranch --config-option "servers:global:http-library=neon"
-RETVAL=$?
+$svn cp -m "Creating a branch" ^/trunk ^/branch/newbranch \
+  || fail "Commits fail with an out-of-date slave"
 
-if [ $RETVAL -eq 0 ]; then
-  say "PASS: Commits succeed even with an out-of-date slave"
-else
-  say "FAIL: Commits fail with an out-of-date slave"
-fi
+say "PASS: Commits succeed even with an out-of-date slave"
 say "Some house-keeping..."
 say "Re-activating the post-commit hook on the master repo: $MASTER_REPOS."
 mv "$MASTER_REPOS/hooks/post-commit_" "$MASTER_REPOS/hooks/post-commit"
