You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/08/14 21:45:28 UTC

svn commit: r1695976 - in /subversion/branches/move-tracking-2/subversion: include/private/svn_editor3e.h libsvn_delta/compat3e.c libsvn_ra/ra_loader.c svnmover/svnmover.c tests/cmdline/svnmover_tests.py

Author: julianfoad
Date: Fri Aug 14 19:45:28 2015
New Revision: 1695976

URL: http://svn.apache.org/r1695976
Log:
On the 'move-tracking-2' branch: More support for top-level (that is,
non-nested) branches.

In the underlying (old) repository, store the versioned content of each
branch hierarchy under a top-level directory named 'top0' for the hierarchy
rooted at top-level branch 0, and so on.

* subversion/include/private/svn_editor3e.h
  (svn_editor3__ev3_from_delta_for_commit): Remove the 'base_relpath'
    parameter.

* subversion/libsvn_delta/compat3e.c
  (ev3_from_delta_baton_t): Remove the 'base_relpath' field.
  (get_unsorted_paths): Remove the 'base_relpath' parameter.
  (apply_change): Adjust to having no base_relpath.
  (branch_get_top_num): New function.
  (branch_get_storage_root_rrpath): Prefix the path with 'top<N>/'.
  (drive_changes_branch): Adjust to having no base_relpath. Make it appear
    that B0 was created (as an empty dir) in r0.
  (wrap_fetch_baton_t,
   wrap_fetch_func): New wrapper to make it appear that B0 was created (as
    an empty dir) in r0.
  (svn_editor3_in_memory): Use that wrapper.
  (svn_editor3__ev3_from_delta_for_commit): Use that wrapper. Adjust to
    having no base_relpath.
  (svn_editor3__insert_shims,
   svn_editor3__ev3_from_delta_for_update): Track the change to
    svn_editor3__ev3_from_delta_for_commit().

* subversion/libsvn_ra/ra_loader.c
  (svn_ra_get_commit_editor_ev3): Adjust to having no base_relpath.

* subversion/svnmover/svnmover.c
  (wc_create): Ensure the RA session is parented at the repository root, not
    at the specified svnmover URL path.

* subversion/tests/cmdline/svnmover_tests.py
  (test_svnmover): Don't run 'svn log' if not needed, because the given URL
    is now an svnmover-only URL, not a valid URL in the underlying repo.
  (basic_svnmover,
   nested_replaces): Adjust the expected log paths to begin with '/top0'.

Modified:
    subversion/branches/move-tracking-2/subversion/include/private/svn_editor3e.h
    subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c
    subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c
    subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c
    subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py

Modified: subversion/branches/move-tracking-2/subversion/include/private/svn_editor3e.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/private/svn_editor3e.h?rev=1695976&r1=1695975&r2=1695976&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/private/svn_editor3e.h (original)
+++ subversion/branches/move-tracking-2/subversion/include/private/svn_editor3e.h Fri Aug 14 19:45:28 2015
@@ -1110,9 +1110,7 @@ typedef struct svn_editor3__shim_connect
  * returned *SHIM_CONNECTOR value to svn_delta__delta_from_ev3_for_commit().
  * SHIM_CONNECTOR may be null if not wanted.
  *
- * REPOS_ROOT_URL is the repository root URL, and BASE_RELPATH is the
- * relative path within the repository of the root directory of the edit.
- * (An Ev1 edit must be rooted at a directory, not at a file.)
+ * REPOS_ROOT_URL is the repository root URL.
  *
  * FETCH_FUNC/FETCH_BATON is a callback by which the shim may retrieve the
  * original or copy-from kind/properties/text for a path being committed.
@@ -1132,7 +1130,6 @@ svn_editor3__ev3_from_delta_for_commit(
                         void *dedit_baton,
                         svn_branch_revision_root_t *branching_txn,
                         const char *repos_root_url,
-                        const char *base_relpath,
                         svn_editor3__shim_fetch_func_t fetch_func,
                         void *fetch_baton,
                         svn_cancel_func_t cancel_func,

Modified: subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c?rev=1695976&r1=1695975&r2=1695976&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_delta/compat3e.c Fri Aug 14 19:45:28 2015
@@ -141,7 +141,7 @@ svn_editor3__insert_shims(
                         &shim_connector,
                         old_deditor, old_dedit_baton,
                         branching_txn,
-                        repos_root, base_relpath,
+                        repos_root,
                         fetch_func, fetch_baton,
                         NULL, NULL /*cancel*/,
                         result_pool, scratch_pool));
@@ -508,8 +508,8 @@ svn_editor3__delta_from_ev3_for_update(
  *     number: see comment in apply_change().
  *
  * ### Have we got our rel-paths in order? Ev1, Ev3 and callbacks may
- *     all expect different paths. 'repos_relpath' or relative to
- *     eb->base_relpath? Leading slash (unimplemented 'send_abs_paths'
+ *     all expect different paths. Are they relative to repos root or to
+ *     some base path? Leading slash (unimplemented 'send_abs_paths'
  *     feature), etc.
  *
  * ### May be tidier for OPEN_ROOT_FUNC callback (see open_root_ev3())
@@ -547,8 +547,6 @@ typedef struct ev3_from_delta_baton_t
   /* Repository root URL
      ### Some code allows this to be null -- but is that valid? */
   const char *repos_root_url;
-  /* Path of the root of the edit, relative to the repository root. */
-  const char *base_relpath;
 
   /* Ev1 changes recorded so far: REPOS_RELPATH -> change_node_ev3_t */
   apr_hash_t *changes;
@@ -559,32 +557,19 @@ typedef struct ev3_from_delta_baton_t
   apr_pool_t *edit_pool;
 } ev3_from_delta_baton_t;
 
-/* Get all the (Ev1) paths that have changes. Return only paths at or below
- * BASE_RELPATH, and return them relative to BASE_RELPATH.
- *
- * ### Instead, we should probably avoid adding paths outside BASE_RELPATH
- *     to CHANGES in the first place, and not allow them here.
+/* Get all the (Ev1) paths that have changes.
  */
 static const apr_array_header_t *
 get_unsorted_paths(apr_hash_t *changes,
-                   const char *base_relpath,
                    apr_pool_t *scratch_pool)
 {
   svn_array_t *paths = svn_array_make(scratch_pool);
   apr_hash_index_t *hi;
 
-  /* Build a new array with just the paths, trimmed to relative paths for
-     the Ev1 drive.  */
   for (hi = apr_hash_first(scratch_pool, changes); hi; hi = apr_hash_next(hi))
     {
       const char *this_path = apr_hash_this_key(hi);
-      const char *this_relpath = svn_relpath_skip_ancestor(base_relpath,
-                                                           this_path);
-
-      if (this_relpath)
-        {
-          SVN_ARRAY_PUSH(paths) = this_relpath;
-        }
+      SVN_ARRAY_PUSH(paths) = this_path;
     }
 
   return paths;
@@ -775,7 +760,7 @@ drive_ev1_props(const char *repos_relpat
 }
 
 /* Drive the Ev1 editor with the change recorded in EB->changes for the
- * path EV1_RELPATH (which is relative to EB->base_relpath).
+ * path EV1_RELPATH.
  *
  * Conforms to svn_delta_path_driver_cb_func_t.
  */
@@ -788,9 +773,7 @@ apply_change(void **dir_baton,
 {
   apr_pool_t *scratch_pool = result_pool;
   const ev3_from_delta_baton_t *eb = callback_baton;
-  const char *relpath = svn_relpath_join(eb->base_relpath, ev1_relpath,
-                                         scratch_pool);
-  const change_node_t *change = svn_hash_gets(eb->changes, relpath);
+  const change_node_t *change = svn_hash_gets(eb->changes, ev1_relpath);
   void *file_baton = NULL;
   apr_hash_t *base_props;
 
@@ -800,7 +783,7 @@ apply_change(void **dir_baton,
   /* Typically, we are not creating new directory batons.  */
   *dir_baton = NULL;
 
-  SVN_ERR(fetch_base_props(&base_props, eb->changes, relpath,
+  SVN_ERR(fetch_base_props(&base_props, eb->changes, ev1_relpath,
                            eb->fetch_func, eb->fetch_baton,
                            scratch_pool, scratch_pool));
 
@@ -812,7 +795,7 @@ apply_change(void **dir_baton,
 
       /* Only property edits are allowed on the root.  */
       SVN_ERR_ASSERT(change->action == RESTRUCTURE_NONE);
-      SVN_ERR(drive_ev1_props(relpath, change, base_props,
+      SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props,
                               eb->deditor, *dir_baton, scratch_pool));
 
       /* No further action possible for the root.  */
@@ -914,10 +897,10 @@ apply_change(void **dir_baton,
 
   /* Apply any properties in CHANGE to the node.  */
   if (change->kind == svn_node_dir)
-    SVN_ERR(drive_ev1_props(relpath, change, base_props,
+    SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props,
                             eb->deditor, *dir_baton, scratch_pool));
   else
-    SVN_ERR(drive_ev1_props(relpath, change, base_props,
+    SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props,
                             eb->deditor, file_baton, scratch_pool));
 
   /* Send the text content delta, if new text content is provided. */
@@ -952,25 +935,34 @@ apply_change(void **dir_baton,
  * Old-repository storage paths for branch elements
  * ========================================================================
  *
- *   B0    e0   =>  ^/
- *   B0    e9   =>  ^/.../foo
- *   B0.12 e12  =>  ^/.../trunk
- *   B0.12 e13  =>  ^/.../trunk/.../bar
- *
- * TODO: To support top-level branches, this needs to return disjoint sets
- * of paths for different top-level branches:
+ * To support top-level branches, we map each top-level branch to its own
+ * directory in the old repository, with each nested branch in a subdirectory:
  *
  *   B0  =>  ^/top0/...
  *           ^/top0/.../trunk/...  <= B0.12
  *   B1  =>  ^/top1/...
  *
- * Ultimately it may be better to put each branch in a separate top-level dir:
+ * It may be better to put each branch in its own directory:
  *
  *   B0     =>  ^/B0/...
  *   B0.12  =>  ^/B0.12/...
  *   B1     =>  ^/B1/...
+ *
+ * (A branch root is not necessarily a directory, it could be a file.)
  */
 
+/*  */
+static int
+branch_get_top_num(const svn_branch_state_t *branch,
+                   apr_pool_t *scratch_pool)
+{
+  while (branch->outer_branch)
+    {
+      branch = branch->outer_branch;
+    }
+  return branch->outer_eid;
+}
+
 /* Get the old-repository path for the storage of the root element of BRANCH.
  *
  * Currently, this is the same as the nested-branching hierarchical path
@@ -980,7 +972,11 @@ static const char *
 branch_get_storage_root_rrpath(const svn_branch_state_t *branch,
                                apr_pool_t *result_pool)
 {
-  return svn_branch_get_root_rrpath(branch, result_pool);
+  int top_branch_num = branch_get_top_num(branch, result_pool);
+  const char *top_path = apr_psprintf(result_pool, "top%d", top_branch_num);
+  const char *nested_path = svn_branch_get_root_rrpath(branch, result_pool);
+
+  return svn_relpath_join(top_path, nested_path, result_pool);
 }
 
 /* Get the old-repository path for the storage of element EID of BRANCH.
@@ -1697,16 +1693,27 @@ drive_changes_branch(ev3_from_delta_bato
         3. modify/delete/add/replace as needed at each path.
    */
   paths_final = apr_hash_make(scratch_pool);
-  /* ### TODO: map paths of non-0 top-level branch to a hidden path space */
   convert_branch_to_paths_r(paths_final,
                             root_branch,
                             scratch_pool, scratch_pool);
 
   {
-    svn_pathrev_t current = { -1, "" };
+    const char *top_path = branch_get_storage_root_rrpath(root_branch,
+                                                          scratch_pool);
+    svn_pathrev_t current;
 
     current.rev = eb->edited_rev_root->base_rev;
-    SVN_ERR(drive_changes_r("", &current,
+    current.relpath = top_path;
+
+    /* Make it appear that B0 was created (as an empty dir) in r0. */
+    if (current.rev == 0)
+      {
+        change_node_t *change;
+
+        SVN_ERR(insert_change(&change, eb->changes, top_path, RESTRUCTURE_ADD));
+        change->kind = svn_node_dir;
+      }
+    SVN_ERR(drive_changes_r(top_path, &current,
                             paths_final, root_branch->outer_eid,
                             eb, scratch_pool));
   }
@@ -1718,17 +1725,16 @@ drive_changes_branch(ev3_from_delta_bato
 
   /* Make the path driver visit the root dir of the edit. Otherwise, it
      will attempt an open_root() instead, which we already did. */
-  if (! svn_hash_gets(eb->changes, eb->base_relpath))
+  if (! svn_hash_gets(eb->changes, ""))
     {
       change_node_t *change;
 
-      SVN_ERR(insert_change(&change, eb->changes, eb->base_relpath,
-                            RESTRUCTURE_NONE));
+      SVN_ERR(insert_change(&change, eb->changes, "", RESTRUCTURE_NONE));
       change->kind = svn_node_dir;
     }
 
   /* Apply the appropriate Ev1 change to each Ev1-relative path. */
-  paths = get_unsorted_paths(eb->changes, eb->base_relpath, scratch_pool);
+  paths = get_unsorted_paths(eb->changes, scratch_pool);
   SVN_ERR(svn_delta_path_driver2(eb->deditor, eb->dedit_baton,
                                  paths, TRUE /*sort*/,
                                  apply_change, (void *)eb,
@@ -1820,6 +1826,52 @@ editor3_mem_abort(void *baton,
   return SVN_NO_ERROR;
 }
 
+/* Baton for wrap_fetch_func. */
+typedef struct wrap_fetch_baton_t
+{
+  /* Wrapped fetcher */
+  svn_editor3__shim_fetch_func_t fetch_func;
+  void *fetch_baton;
+} wrap_fetch_baton_t;
+
+/* The purpose of this fetcher-wrapper is to make it appear that B0
+ * was created (as an empty dir) in r0.
+ */
+static svn_error_t *
+wrap_fetch_func(svn_node_kind_t *kind,
+                apr_hash_t **props,
+                svn_stringbuf_t **file_text,
+                apr_hash_t **children_names,
+                void *baton,
+                const char *repos_relpath,
+                svn_revnum_t revision,
+                apr_pool_t *result_pool,
+                apr_pool_t *scratch_pool)
+{
+  wrap_fetch_baton_t *b = baton;
+
+  if (revision == 0 && strcmp(repos_relpath, "top0") == 0)
+    {
+      if (kind)
+        *kind = svn_node_dir;
+      if (props)
+        *props = apr_hash_make(result_pool);
+      if (file_text)
+        *file_text = NULL;
+      if (children_names)
+        *children_names = apr_hash_make(result_pool);
+    }
+  else
+    {
+      SVN_ERR(b->fetch_func(kind, props, file_text, children_names,
+                            b->fetch_baton,
+                            repos_relpath, revision,
+                            result_pool, scratch_pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_editor3_in_memory(svn_editor3_t **editor_p,
                       svn_branch_revision_root_t *branching_txn,
@@ -1840,13 +1892,17 @@ svn_editor3_in_memory(svn_editor3_t **ed
     editor3_mem_abort
   };
   ev3_from_delta_baton_t *eb = apr_pcalloc(result_pool, sizeof(*eb));
+  wrap_fetch_baton_t *wb = apr_pcalloc(result_pool, sizeof(*wb));
 
   *editor_p = svn_editor3_create(&editor_funcs, eb,
                                  NULL, NULL /*cancel*/, result_pool);
 
   eb->edited_rev_root = branching_txn;
-  eb->fetch_func = fetch_func;
-  eb->fetch_baton = fetch_baton;
+
+  wb->fetch_func = fetch_func;
+  wb->fetch_baton = fetch_baton;
+  eb->fetch_func = wrap_fetch_func;
+  eb->fetch_baton = wb;
 
   return SVN_NO_ERROR;
 }
@@ -1859,7 +1915,6 @@ svn_editor3__ev3_from_delta_for_commit(
                         void *dedit_baton,
                         svn_branch_revision_root_t *branching_txn,
                         const char *repos_root_url,
-                        const char *base_relpath,
                         svn_editor3__shim_fetch_func_t fetch_func,
                         void *fetch_baton,
                         svn_cancel_func_t cancel_func,
@@ -1880,29 +1935,25 @@ svn_editor3__ev3_from_delta_for_commit(
     editor3_abort
   };
   ev3_from_delta_baton_t *eb = apr_pcalloc(result_pool, sizeof(*eb));
+  wrap_fetch_baton_t *wb = apr_pcalloc(result_pool, sizeof(*wb));
 
   eb->deditor = deditor;
   eb->dedit_baton = dedit_baton;
 
   eb->repos_root_url = apr_pstrdup(result_pool, repos_root_url);
-  eb->base_relpath = apr_pstrdup(result_pool, base_relpath);
 
   eb->changes = apr_hash_make(result_pool);
 
-  eb->fetch_func = fetch_func;
-  eb->fetch_baton = fetch_baton;
+  wb->fetch_func = fetch_func;
+  wb->fetch_baton = fetch_baton;
+  eb->fetch_func = wrap_fetch_func;
+  eb->fetch_baton = wb;
 
   eb->edit_pool = result_pool;
 
   *editor_p = svn_editor3_create(&editor_funcs, eb,
                                  cancel_func, cancel_baton, result_pool);
 
-  /* Find what branch we are editing, based on BASE_RELPATH, and capture
-     its initial state.
-     ### TODO: Instead, have edit operations specify the branch(es) they
-         are operating on, since operations such as "branch"
-         and those that recurse into sub-branches operate on more than one.
-   */
   eb->edited_rev_root = branching_txn;
 
   if (shim_connector)
@@ -1955,7 +2006,7 @@ svn_editor3__ev3_from_delta_for_update(
                         &update_editor->editor,
                         &shim_connector,
                         deditor, dedit_baton,
-                        branching_txn, repos_root_url, base_repos_relpath,
+                        branching_txn, repos_root_url,
                         fetch_func, fetch_baton,
                         cancel_func, cancel_baton,
                         result_pool, scratch_pool));

Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c?rev=1695976&r1=1695975&r2=1695976&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra/ra_loader.c Fri Aug 14 19:45:28 2015
@@ -1023,11 +1023,9 @@ svn_ra_get_commit_editor_ev3(svn_ra_sess
 
   /* Convert to Ev3 */
   {
-    const char *repos_root_url, *session_url, *base_relpath;
+    const char *repos_root_url;
 
     SVN_ERR(svn_ra_get_repos_root2(session, &repos_root_url, pool));
-    SVN_ERR(svn_ra_get_session_url(session, &session_url, pool));
-    base_relpath = svn_uri_skip_ancestor(repos_root_url, session_url, pool);
 
     /*if (! svn_dbg__quiet_mode())
       SVN_ERR(svn_delta__get_debug_editor(&deditor, &dedit_baton,
@@ -1036,7 +1034,7 @@ svn_ra_get_commit_editor_ev3(svn_ra_sess
                         editor,
                         &shim_connector,
                         deditor, dedit_baton, branching_txn,
-                        repos_root_url, base_relpath,
+                        repos_root_url,
                         fetch_func, fetch_baton,
                         NULL, NULL /*cancel*/,
                         pool, pool));

Modified: subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c?rev=1695976&r1=1695975&r2=1695976&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c Fri Aug 14 19:45:28 2015
@@ -245,6 +245,7 @@ wc_create(svnmover_wc_t **wc_p,
                                  result_pool));
   SVN_ERR(svn_ra_get_latest_revnum(wc->ra_session, &wc->head_revision,
                                    scratch_pool));
+  SVN_ERR(svn_ra_reparent(wc->ra_session, wc->repos_root_url, scratch_pool));
 
   SVN_ERR(wc_checkout(wc, base_revision, scratch_pool));
   *wc_p = wc;

Modified: subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py?rev=1695976&r1=1695975&r2=1695976&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py (original)
+++ subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py Fri Aug 14 19:45:28 2015
@@ -177,19 +177,19 @@ def test_svnmover(repo_url, expected_pat
   if not any(map(_commit_re.match, outlines)):
     raise svntest.main.SVNLineUnequal(str(outlines))
 
-  # Now, run 'svn log -vq -rHEAD'
-  changed_paths = []
-  exit_code, outlines, errlines = \
-    svntest.main.run_svn(None, 'log', '-vqrHEAD', repo_url)
-  if errlines:
-    raise svntest.Failure("Unable to verify commit with 'svn log': %s"
-                          % (str(errlines)))
-  for line in outlines:
-    match = _log_re.match(line)
-    if match:
-      changed_paths.append(match.group(1).rstrip('\n\r'))
-
   if expected_path_changes is not None:
+    # Now, run 'svn log -vq -rHEAD'
+    changed_paths = []
+    exit_code, outlines, errlines = \
+      svntest.main.run_svn(None, 'log', '-vqrHEAD', repo_url)
+    if errlines:
+      raise svntest.Failure("Unable to verify commit with 'svn log': %s"
+                            % (str(errlines)))
+    for line in outlines:
+      match = _log_re.match(line)
+      if match:
+        changed_paths.append(match.group(1).rstrip('\n\r'))
+
     expected_path_changes.sort()
     changed_paths.sort()
     if changed_paths != expected_path_changes:
@@ -254,30 +254,30 @@ def basic_svnmover(sbox):
 
   # revision 2
   test_svnmover(sbox.repo_url,
-                ['A /foo'
+                ['A /top0/foo'
                  ], # ---------
                 'mkdir foo')
 
   # revision 3
   test_svnmover(sbox.repo_url,
-                ['A /z.c',
+                ['A /top0/z.c',
                  ], # ---------
                 'put', empty_file, 'z.c')
 
   # revision 4
   test_svnmover(sbox.repo_url,
-                ['A /foo/z.c (from /z.c:3)',
-                 'A /foo/bar (from /foo:3)',
+                ['A /top0/foo/z.c (from /top0/z.c:3)',
+                 'A /top0/foo/bar (from /top0/foo:3)',
                  ], # ---------
                 'cp 3 z.c foo/z.c',
                 'cp 3 foo foo/bar')
 
   # revision 5
   test_svnmover(sbox.repo_url,
-                ['A /zig (from /foo:4)',
-                 'D /zig/bar',
-                 'D /foo',
-                 'A /zig/zag (from /foo:4)',
+                ['A /top0/zig (from /top0/foo:4)',
+                 'D /top0/zig/bar',
+                 'D /top0/foo',
+                 'A /top0/zig/zag (from /top0/foo:4)',
                  ], # ---------
                 'cp 4 foo zig',
                 'rm zig/bar',
@@ -285,28 +285,28 @@ def basic_svnmover(sbox):
 
   # revision 6
   test_svnmover(sbox.repo_url,
-                ['D /z.c',
-                 'A /zig/zag/bar/y.c (from /z.c:5)',
-                 'A /zig/zag/bar/x.c (from /z.c:3)',
+                ['D /top0/z.c',
+                 'A /top0/zig/zag/bar/y.c (from /top0/z.c:5)',
+                 'A /top0/zig/zag/bar/x.c (from /top0/z.c:3)',
                  ], # ---------
                 'mv z.c zig/zag/bar/y.c',
                 'cp 3 z.c zig/zag/bar/x.c')
 
   # revision 7
   test_svnmover(sbox.repo_url,
-                ['D /zig/zag/bar/y.c',
-                 'A /zig/zag/bar/y_y.c (from /zig/zag/bar/y.c:6)',
-                 'A /zig/zag/bar/y%20y.c (from /zig/zag/bar/y.c:6)',
+                ['D /top0/zig/zag/bar/y.c',
+                 'A /top0/zig/zag/bar/y_y.c (from /top0/zig/zag/bar/y.c:6)',
+                 'A /top0/zig/zag/bar/y%20y.c (from /top0/zig/zag/bar/y.c:6)',
                  ], # ---------
                 'mv zig/zag/bar/y.c zig/zag/bar/y_y.c',
                 'cp HEAD zig/zag/bar/y.c zig/zag/bar/y%20y.c')
 
   # revision 8
   test_svnmover(sbox.repo_url,
-                ['D /zig/zag/bar/y_y.c',
-                 'A /zig/zag/bar/z_z1.c (from /zig/zag/bar/y_y.c:7)',
-                 'A /zig/zag/bar/z%20z.c (from /zig/zag/bar/y%20y.c:7)',
-                 'A /zig/zag/bar/z_z2.c (from /zig/zag/bar/y_y.c:7)',
+                ['D /top0/zig/zag/bar/y_y.c',
+                 'A /top0/zig/zag/bar/z_z1.c (from /top0/zig/zag/bar/y_y.c:7)',
+                 'A /top0/zig/zag/bar/z%20z.c (from /top0/zig/zag/bar/y%20y.c:7)',
+                 'A /top0/zig/zag/bar/z_z2.c (from /top0/zig/zag/bar/y_y.c:7)',
                  ], #---------
                 'mv zig/zag/bar/y_y.c zig/zag/bar/z_z1.c',
                 'cp HEAD zig/zag/bar/y%20y.c zig/zag/bar/z%20z.c',
@@ -315,11 +315,11 @@ def basic_svnmover(sbox):
 
   # revision 9
   test_svnmover(sbox.repo_url,
-                ['D /zig/zag',
-                 'A /zig/foo (from /zig/zag:8)',
-                 'D /zig/foo/bar/z%20z.c',
-                 'D /zig/foo/bar/z_z2.c',
-                 'R /zig/foo/bar/z_z1.c (from /zig/zag/bar/x.c:6)',
+                ['D /top0/zig/zag',
+                 'A /top0/zig/foo (from /top0/zig/zag:8)',
+                 'D /top0/zig/foo/bar/z%20z.c',
+                 'D /top0/zig/foo/bar/z_z2.c',
+                 'R /top0/zig/foo/bar/z_z1.c (from /top0/zig/zag/bar/x.c:6)',
                  ], #---------
                 'mv zig/zag zig/foo',
                 'rm zig/foo/bar/z_z1.c',
@@ -329,15 +329,15 @@ def basic_svnmover(sbox):
 
   # revision 10
   test_svnmover(sbox.repo_url,
-                ['R /zig/foo/bar (from /zig/z.c:9)',
+                ['R /top0/zig/foo/bar (from /top0/zig/z.c:9)',
                  ], #---------
                 'rm zig/foo/bar',
                 'cp 9 zig/z.c zig/foo/bar')
 
   # revision 11
   test_svnmover(sbox.repo_url,
-                ['R /zig/foo/bar (from /zig/foo/bar:9)',
-                 'D /zig/foo/bar/z_z1.c',
+                ['R /top0/zig/foo/bar (from /top0/zig/foo/bar:9)',
+                 'D /top0/zig/foo/bar/z_z1.c',
                  ], #---------
                 'rm zig/foo/bar',
                 'cp 9 zig/foo/bar zig/foo/bar',
@@ -345,19 +345,19 @@ def basic_svnmover(sbox):
 
   # revision 12
   test_svnmover(sbox.repo_url,
-                ['R /zig/foo (from /zig/foo/bar:11)',
+                ['R /top0/zig/foo (from /top0/zig/foo/bar:11)',
                  ], #---------
                 'rm zig/foo',
                 'cp head zig/foo/bar zig/foo')
 
   # revision 13
   test_svnmover(sbox.repo_url,
-                ['D /zig',
-                 'A /foo (from /foo:4)',
-                 'A /foo/foo (from /foo:4)',
-                 'A /foo/foo/foo (from /foo:4)',
-                 'D /foo/foo/bar',
-                 'R /foo/foo/foo/bar (from /foo:4)',
+                ['D /top0/zig',
+                 'A /top0/foo (from /top0/foo:4)',
+                 'A /top0/foo/foo (from /top0/foo:4)',
+                 'A /top0/foo/foo/foo (from /top0/foo:4)',
+                 'D /top0/foo/foo/bar',
+                 'R /top0/foo/foo/foo/bar (from /top0/foo:4)',
                  ], #---------
                 'rm zig',
                 'cp 4 foo foo',
@@ -369,9 +369,9 @@ def basic_svnmover(sbox):
 
   # revision 14
   test_svnmover(sbox.repo_url,
-                ['A /boozle (from /foo:4)',
-                 'A /boozle/buz',
-                 'A /boozle/buz/nuz',
+                ['A /top0/boozle (from /top0/foo:4)',
+                 'A /top0/boozle/buz',
+                 'A /top0/boozle/buz/nuz',
                  ], #---------
                 'cp 4 foo boozle',
                 'mkdir boozle/buz',
@@ -379,9 +379,9 @@ def basic_svnmover(sbox):
 
   # revision 15
   test_svnmover(sbox.repo_url,
-                ['A /boozle/buz/svnmover-test.py',
-                 'A /boozle/guz (from /boozle/buz:14)',
-                 'A /boozle/guz/svnmover-test.py',
+                ['A /top0/boozle/buz/svnmover-test.py',
+                 'A /top0/boozle/guz (from /top0/boozle/buz:14)',
+                 'A /top0/boozle/guz/svnmover-test.py',
                  ], #---------
                 'put', empty_file, 'boozle/buz/svnmover-test.py',
                 'cp 14 boozle/buz boozle/guz',
@@ -389,7 +389,7 @@ def basic_svnmover(sbox):
 
   # revision 16
   test_svnmover(sbox.repo_url,
-                ['R /boozle/guz/svnmover-test.py',
+                ['R /top0/boozle/guz/svnmover-test.py',
                  ], #---------
                 'put', empty_file, 'boozle/buz/svnmover-test.py',
                 'rm boozle/guz/svnmover-test.py',
@@ -453,16 +453,16 @@ rm A/B/C/Y
 
   # ### TODO: need a smarter run_and_verify_log() that verifies copyfrom
   expected_output = svntest.verify.UnorderedRegexListOutput(map(re.escape, [
-    '   R /A (from /X/Y/Z:1)',
-    '   A /A/B (from /A/B:1)',
-    '   R /A/B/C (from /X:1)',
-    '   R /M (from /A/B/C:1)',
-    '   A /M/N (from /M/N:1)',
-    '   R /M/N/O (from /A:1)',
-    '   R /X (from /M/N/O:1)',
-    '   A /X/Y (from /X/Y:1)',
-    '   R /X/Y/Z (from /M:1)',
-    '   D /A/B/C/Y',
+    '   R /top0/A (from /top0/X/Y/Z:1)',
+    '   A /top0/A/B (from /top0/A/B:1)',
+    '   R /top0/A/B/C (from /top0/X:1)',
+    '   R /top0/M (from /top0/A/B/C:1)',
+    '   A /top0/M/N (from /top0/M/N:1)',
+    '   R /top0/M/N/O (from /top0/A:1)',
+    '   R /top0/X (from /top0/M/N/O:1)',
+    '   A /top0/X/Y (from /top0/X/Y:1)',
+    '   R /top0/X/Y/Z (from /top0/M:1)',
+    '   D /top0/A/B/C/Y',
   ]) + [
     '^-', '^r2', '^-', '^Changed paths:',
   ])