You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/08/10 20:06:33 UTC

svn commit: r984153 [13/39] - in /subversion/branches/ignore-mergeinfo: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/hudson/ build/hudson/jobs/subversion-1.6.x-solaris/ build/hudson/jobs/subversion-1.6.x-ubuntu/ build/hu...

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/copy.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/copy.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/copy.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/copy.c Tue Aug 10 18:06:17 2010
@@ -70,33 +70,30 @@
 
 /* Obtain the implied mergeinfo and the existing mergeinfo of the
    source path, combine them and return the result in
-   *TARGET_MERGEINFO.  ADM_ACCESS may be NULL, if SRC_PATH_OR_URL is an
-   URL.  If NO_REPOS_ACCESS is set, this function is disallowed from
-   consulting the repository about anything.  RA_SESSION may be NULL but
-   only if NO_REPOS_ACCESS is true.  */
+   *TARGET_MERGEINFO.  One of LOCAL_ABSPATH and SRC_URL must be valid,
+   the other must be NULL. */
 static svn_error_t *
 calculate_target_mergeinfo(svn_ra_session_t *ra_session,
                            apr_hash_t **target_mergeinfo,
-                           svn_wc_adm_access_t *adm_access,
-                           const char *src_path_or_url,
+                           const char *local_abspath,
+                           const char *src_url,
                            svn_revnum_t src_revnum,
-                           svn_boolean_t no_repos_access,
                            svn_client_ctx_t *ctx,
                            apr_pool_t *pool)
 {
   const svn_wc_entry_t *entry = NULL;
   svn_boolean_t locally_added = FALSE;
-  const char *src_url;
   apr_hash_t *src_mergeinfo = NULL;
 
+  SVN_ERR_ASSERT((local_abspath && !src_url) || (!local_abspath && src_url));
+
   /* If we have a schedule-add WC path (which was not copied from
      elsewhere), it doesn't have any repository mergeinfo, so don't
      bother checking. */
-  if (adm_access)
+  if (local_abspath)
     {
-      const char *local_abspath;
+      SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
-      SVN_ERR(svn_dirent_get_absolute(&local_abspath, src_path_or_url, pool));
       SVN_ERR(svn_wc__get_entry_versioned(&entry, ctx->wc_ctx, local_abspath,
                                           svn_node_unknown, FALSE, FALSE,
                                           pool, pool));
@@ -112,42 +109,23 @@ calculate_target_mergeinfo(svn_ra_sessio
                                              pool, pool));
         }
     }
-  else
-    {
-      src_url = src_path_or_url;
-    }
 
   if (! locally_added)
     {
-      if (! no_repos_access)
-        {
-          /* Fetch any existing (explicit) mergeinfo.  We'll temporarily
-             reparent to the target URL here, just to keep the code simple.
-             We could, as an alternative, first see if the target URL was a
-             child of the session URL and use the relative "remainder", 
-             falling back to this reparenting as necessary.  */
-          const char *old_session_url = NULL;
-          SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url,
-                                                    ra_session, src_url, pool));
-          SVN_ERR(svn_client__get_repos_mergeinfo(ra_session, &src_mergeinfo,
-                                                  "", src_revnum,
-                                                  svn_mergeinfo_inherited,
-                                                  TRUE, pool));
-          if (old_session_url)
-            SVN_ERR(svn_ra_reparent(ra_session, old_session_url, pool));
-        }
-      else
-        {
-          svn_boolean_t inherited;
-          const char *local_abspath;
-
-          SVN_ERR(svn_dirent_get_absolute(&local_abspath, src_path_or_url,
-                                          pool));
-          SVN_ERR(svn_client__get_wc_mergeinfo(&src_mergeinfo, &inherited,
-                                               svn_mergeinfo_inherited,
-                                               local_abspath, NULL,
-                                               NULL, ctx, pool, pool));
-        }
+      /* Fetch any existing (explicit) mergeinfo.  We'll temporarily
+         reparent to the target URL here, just to keep the code simple.
+         We could, as an alternative, first see if the target URL was a
+         child of the session URL and use the relative "remainder",
+         falling back to this reparenting as necessary.  */
+      const char *old_session_url = NULL;
+      SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url,
+                                                ra_session, src_url, pool));
+      SVN_ERR(svn_client__get_repos_mergeinfo(ra_session, &src_mergeinfo,
+                                              "", src_revnum,
+                                              svn_mergeinfo_inherited,
+                                              TRUE, pool));
+      if (old_session_url)
+        SVN_ERR(svn_ra_reparent(ra_session, old_session_url, pool));
     }
 
   *target_mergeinfo = src_mergeinfo;
@@ -177,7 +155,7 @@ extend_wc_mergeinfo(const char *target_a
 
   return svn_error_return(
     svn_client__record_wc_mergeinfo(target_abspath, wc_mergeinfo,
-                                    ctx, pool));
+                                    FALSE, ctx, pool));
 }
 
 /* Find the longest common ancestor of paths in COPY_PAIRS.  If
@@ -258,63 +236,126 @@ get_copy_pair_ancestors(const apr_array_
 }
 
 
-/* Copy each COPY_PAIR->SRC into COPY_PAIR->DST.  Use POOL for temporary
-   allocations. */
+struct do_wc_to_wc_copies_with_write_lock_baton {
+  const apr_array_header_t *copy_pairs;
+  svn_client_ctx_t *ctx;
+  const char *dst_parent;
+};
+
+/* The guts of do_wc_to_wc_copies */
 static svn_error_t *
-do_wc_to_wc_copies(const apr_array_header_t *copy_pairs,
-                   svn_client_ctx_t *ctx,
-                   apr_pool_t *pool)
+do_wc_to_wc_copies_with_write_lock(void *baton,
+                                   apr_pool_t *result_pool,
+                                   apr_pool_t *scratch_pool)
 {
+  struct do_wc_to_wc_copies_with_write_lock_baton *b = baton;
   int i;
-  apr_pool_t *iterpool = svn_pool_create(pool);
-  const char *dst_parent;
-  svn_wc_adm_access_t *dst_access;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
   svn_error_t *err = SVN_NO_ERROR;
 
-  get_copy_pair_ancestors(copy_pairs, NULL, &dst_parent, NULL, pool);
-  if (copy_pairs->nelts == 1)
-    dst_parent = svn_dirent_dirname(dst_parent, pool);
-
-  /* Because all copies are to the same destination directory, we can open
-     the directory once, and use it for each copy. */
-  /* ### If we didn't potentially use DST_ACCESS as the SRC_ACCESS, we
-     ### could use a read lock here. */
-  SVN_ERR(svn_wc__adm_open_in_context(&dst_access, ctx->wc_ctx, dst_parent,
-                           TRUE, -1, ctx->cancel_func, ctx->cancel_baton,
-                           pool));
-
-  for (i = 0; i < copy_pairs->nelts; i++)
+  for (i = 0; i < b->copy_pairs->nelts; i++)
     {
-      const char *dst_parent_abspath;
       const char *dst_abspath;
-      svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
+      svn_client__copy_pair_t *pair = APR_ARRAY_IDX(b->copy_pairs, i,
                                                     svn_client__copy_pair_t *);
       svn_pool_clear(iterpool);
 
       /* Check for cancellation */
-      if (ctx->cancel_func)
-        SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+      if (b->ctx->cancel_func)
+        SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton));
 
       /* Perform the copy */
-      SVN_ERR(svn_dirent_get_absolute(&pair->src_abs, pair->src, pool));
-      SVN_ERR(svn_dirent_get_absolute(&dst_parent_abspath, pair->dst_parent,
-                                      pool));
-      dst_abspath = svn_dirent_join(dst_parent_abspath, pair->base_name,
+      dst_abspath = svn_dirent_join(pair->dst_parent_abspath, pair->base_name,
                                     iterpool);
-      err = svn_wc_copy3(ctx->wc_ctx, pair->src_abs, dst_abspath,
-                         ctx->cancel_func, ctx->cancel_baton,
-                         ctx->notify_func2, ctx->notify_baton2, iterpool);
+      err = svn_wc_copy3(b->ctx->wc_ctx, pair->src, dst_abspath,
+                         b->ctx->cancel_func, b->ctx->cancel_baton,
+                         b->ctx->notify_func2, b->ctx->notify_baton2, iterpool);
       if (err)
         break;
     }
   svn_pool_destroy(iterpool);
 
-  svn_io_sleep_for_timestamps(dst_parent, pool);
+  svn_io_sleep_for_timestamps(b->dst_parent, scratch_pool);
   SVN_ERR(err);
+  return SVN_NO_ERROR;
+}
 
-  return svn_error_return(svn_wc_adm_close2(dst_access, pool));
+/* Copy each COPY_PAIR->SRC into COPY_PAIR->DST.  Use POOL for temporary
+   allocations. */
+static svn_error_t *
+do_wc_to_wc_copies(const apr_array_header_t *copy_pairs,
+                   svn_client_ctx_t *ctx,
+                   apr_pool_t *pool)
+{
+  const char *dst_parent, *dst_parent_abspath;
+  struct do_wc_to_wc_copies_with_write_lock_baton baton;
+
+  get_copy_pair_ancestors(copy_pairs, NULL, &dst_parent, NULL, pool);
+  if (copy_pairs->nelts == 1)
+    dst_parent = svn_dirent_dirname(dst_parent, pool);
+
+  SVN_ERR(svn_dirent_get_absolute(&dst_parent_abspath, dst_parent, pool));
+
+  baton.copy_pairs = copy_pairs;
+  baton.ctx = ctx;
+  baton.dst_parent = dst_parent;
+  SVN_ERR(svn_wc__call_with_write_lock(do_wc_to_wc_copies_with_write_lock,
+                                       &baton, ctx->wc_ctx, dst_parent_abspath,
+                                       pool, pool));
+
+  return SVN_NO_ERROR;
 }
 
+struct do_wc_to_wc_moves_with_locks_baton {
+  svn_client_ctx_t *ctx;
+  svn_client__copy_pair_t *pair;
+  const char *dst_parent_abspath;
+  svn_boolean_t lock_src;
+  svn_boolean_t lock_dst;
+};
+
+/* The locked bit of do_wc_to_wc_moves. */
+static svn_error_t *
+do_wc_to_wc_moves_with_locks2(void *baton,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool)
+{
+  struct do_wc_to_wc_moves_with_locks_baton *b = baton;
+  const char *dst_abspath;
+
+  dst_abspath = svn_dirent_join(b->dst_parent_abspath, b->pair->base_name,
+                                scratch_pool);
+
+  SVN_ERR(svn_wc_copy3(b->ctx->wc_ctx, b->pair->src, dst_abspath,
+                       b->ctx->cancel_func, b->ctx->cancel_baton,
+                       b->ctx->notify_func2, b->ctx->notify_baton2,
+                       scratch_pool));
+
+  SVN_ERR(svn_wc_delete4(b->ctx->wc_ctx, b->pair->src, FALSE, FALSE,
+                         b->ctx->cancel_func, b->ctx->cancel_baton,
+                         b->ctx->notify_func2, b->ctx->notify_baton2,
+                         scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Wrapper to add an optional second lock */
+static svn_error_t *
+do_wc_to_wc_moves_with_locks1(void *baton,
+                              apr_pool_t *result_pool,
+                              apr_pool_t *scratch_pool)
+{
+  struct do_wc_to_wc_moves_with_locks_baton *b = baton;
+
+  if (b->lock_dst)
+    SVN_ERR(svn_wc__call_with_write_lock(do_wc_to_wc_moves_with_locks2, b,
+                                         b->ctx->wc_ctx, b->dst_parent_abspath,
+                                         result_pool, scratch_pool));
+  else
+    SVN_ERR(do_wc_to_wc_moves_with_locks2(b, result_pool, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
 
 /* Move each COPY_PAIR->SRC into COPY_PAIR->DST, deleting COPY_PAIR->SRC
    afterwards.  Use POOL for temporary allocations. */
@@ -330,14 +371,8 @@ do_wc_to_wc_moves(const apr_array_header
 
   for (i = 0; i < copy_pairs->nelts; i++)
     {
-      svn_wc_adm_access_t *src_access;
-      svn_wc_adm_access_t *dst_access;
-      svn_boolean_t close_dst_access = FALSE;
-      svn_boolean_t close_src_access = FALSE;
-      const char *src_parent;
       const char *src_parent_abspath;
-      const char *dst_abspath;
-      const char *dst_parent_abspath;
+      struct do_wc_to_wc_moves_with_locks_baton baton;
 
       svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
                                                     svn_client__copy_pair_t *);
@@ -347,83 +382,46 @@ do_wc_to_wc_moves(const apr_array_header
       if (ctx->cancel_func)
         SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
 
-      src_parent = svn_dirent_dirname(pair->src, iterpool);
-      SVN_ERR(svn_dirent_get_absolute(&src_parent_abspath, src_parent,
-                                      iterpool));
-      SVN_ERR(svn_dirent_get_absolute(&dst_parent_abspath, pair->dst_parent,
-                                      iterpool));
+      src_parent_abspath = svn_dirent_dirname(pair->src, iterpool);
 
-      /* We now need to open the right combination of batons.
+      /* We now need to lock the right combination of batons.
          Four cases:
            1) src_parent == dst_parent
            2) src_parent is parent of dst_parent
            3) dst_parent is parent of src_parent
-           4) src_parent and dst_parent are disjoint */
-      if (strcmp(src_parent_abspath, dst_parent_abspath) == 0)
+           4) src_parent and dst_parent are disjoint
+         We can handle 1) as either 2) or 3) */
+      if (strcmp(src_parent_abspath, pair->dst_parent_abspath) == 0
+          || svn_dirent_is_child(src_parent_abspath, pair->dst_parent_abspath,
+                                 iterpool))
         {
-          SVN_ERR(svn_wc__adm_open_in_context(&src_access, ctx->wc_ctx,
-                                              src_parent, TRUE, -1,
-                                              ctx->cancel_func,
-                                              ctx->cancel_baton, iterpool));
-          dst_access = src_access;
-          close_src_access = TRUE;
+          baton.lock_src = TRUE;
+          baton.lock_dst = FALSE;
         }
-      else if (svn_dirent_is_child(src_parent_abspath, dst_parent_abspath,
+      else if (svn_dirent_is_child(pair->dst_parent_abspath, src_parent_abspath,
                                    iterpool))
         {
-          SVN_ERR(svn_wc__adm_open_in_context(&src_access, ctx->wc_ctx,
-                                              src_parent, TRUE, -1,
-                                              ctx->cancel_func,
-                                              ctx->cancel_baton, iterpool));
-          SVN_ERR(svn_wc_adm_retrieve(&dst_access, src_access,
-                                      pair->dst_parent, iterpool));
-          close_src_access = TRUE;
-        }
-      else if (svn_dirent_is_child(dst_parent_abspath, src_parent_abspath,
-                                   iterpool))
-        {
-          SVN_ERR(svn_wc__adm_open_in_context(&dst_access, ctx->wc_ctx,
-                                              pair->dst_parent, TRUE, -1,
-                                              ctx->cancel_func,
-                                              ctx->cancel_baton, iterpool));
-          SVN_ERR(svn_wc_adm_retrieve(&src_access, dst_access, src_parent,
-                                      iterpool));
-          close_dst_access = TRUE;
+          baton.lock_src = FALSE;
+          baton.lock_dst = TRUE;
         }
       else
         {
-          SVN_ERR(svn_wc__adm_open_in_context(&src_access, ctx->wc_ctx,
-                                              src_parent, TRUE, -1,
-                                              ctx->cancel_func,
-                                              ctx->cancel_baton, iterpool));
-          SVN_ERR(svn_wc__adm_open_in_context(&dst_access, ctx->wc_ctx,
-                                              pair->dst_parent, TRUE, -1,
-                                              ctx->cancel_func,
-                                              ctx->cancel_baton, iterpool));
-          close_dst_access = TRUE;
-          close_src_access = TRUE;
+          baton.lock_src = TRUE;
+          baton.lock_dst = TRUE;
         }
 
       /* Perform the copy and then the delete. */
-      SVN_ERR(svn_dirent_get_absolute(&pair->src_abs, pair->src, pool));
-      dst_abspath = svn_dirent_join(dst_parent_abspath, pair->base_name,
-                                    iterpool);
-      err = svn_wc_copy3(ctx->wc_ctx, pair->src_abs, dst_abspath,
-                         ctx->cancel_func, ctx->cancel_baton,
-                         ctx->notify_func2, ctx->notify_baton2, iterpool);
-      if (err)
-        break;
+      baton.ctx = ctx;
+      baton.pair = pair;
+      baton.dst_parent_abspath = pair->dst_parent_abspath;
+      if (baton.lock_src)
+        SVN_ERR(svn_wc__call_with_write_lock(do_wc_to_wc_moves_with_locks1,
+                                             &baton,
+                                             ctx->wc_ctx, src_parent_abspath,
+                                             iterpool, iterpool));
+      else
+        SVN_ERR(do_wc_to_wc_moves_with_locks1(&baton, iterpool, iterpool));
 
-      /* Perform the delete. */
-      SVN_ERR(svn_wc_delete4(ctx->wc_ctx, pair->src_abs, FALSE, FALSE,
-                             ctx->cancel_func, ctx->cancel_baton,
-                             ctx->notify_func2, ctx->notify_baton2,
-                             iterpool));
-
-      if (close_dst_access)
-        SVN_ERR(svn_wc_adm_close2(dst_access, iterpool));
-      if (close_src_access)
-        SVN_ERR(svn_wc_adm_close2(src_access, iterpool));
     }
   svn_pool_destroy(iterpool);
 
@@ -469,22 +467,24 @@ wc_to_wc_copy(const apr_array_header_t *
                                  _("Path '%s' already exists"),
                                  svn_dirent_local_style(pair->dst, pool));
 
-      svn_dirent_split(pair->dst, &pair->dst_parent, &pair->base_name, pool);
+      svn_dirent_split(pair->dst, &pair->dst_parent_abspath, &pair->base_name,
+                       pool);
 
       /* Make sure the destination parent is a directory and produce a clear
          error message if it is not. */
-      SVN_ERR(svn_io_check_path(pair->dst_parent, &dst_parent_kind, iterpool));
+      SVN_ERR(svn_io_check_path(pair->dst_parent_abspath, &dst_parent_kind,
+                                iterpool));
       if (make_parents && dst_parent_kind == svn_node_none)
         {
-          SVN_ERR(svn_client__make_local_parents(pair->dst_parent, TRUE, ctx,
-                                                 iterpool));
+          SVN_ERR(svn_client__make_local_parents(pair->dst_parent_abspath,
+                                                 TRUE, ctx, iterpool));
         }
       else if (dst_parent_kind != svn_node_dir)
         {
           return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
                                    _("Path '%s' is not a directory"),
-                                   svn_dirent_local_style(pair->dst_parent,
-                                                        pool));
+                                   svn_dirent_local_style(
+                                     pair->dst_parent_abspath, pool));
         }
     }
 
@@ -667,9 +667,9 @@ find_absent_parents1(svn_ra_session_t *r
    found. Push each nonexistent URL onto the array NEW_DIRS,
    allocating in POOL.  Raise an error if the existing node is not a
    directory.
- 
+
    Set *TOP_DST_URL and the RA session's root to the existing node's URL.
-  
+
    ### Multiple requests for HEAD (SVN_INVALID_REVNUM) make this
    ### implementation susceptible to race conditions.  */
 static svn_error_t *
@@ -781,12 +781,13 @@ repos_to_repos_copy(svn_commit_info_t **
                                           pair->src, &pair->src_peg_revision,
                                           &pair->src_op_revision,
                                           &dead_end_rev, ctx, pool));
-     
+
       /* Go ahead and grab mergeinfo from the source, too. */
       SVN_ERR(svn_client__ensure_ra_session_url(&ignored_url, ra_session,
                                                 pair->src, pool));
-      SVN_ERR(calculate_target_mergeinfo(ra_session, &mergeinfo, NULL, pair->src,
-                                         pair->src_revnum, FALSE, ctx, pool));
+      SVN_ERR(calculate_target_mergeinfo(ra_session, &mergeinfo, NULL,
+                                         pair->src,
+                                         pair->src_revnum, ctx, pool));
       if (mergeinfo)
         SVN_ERR(svn_mergeinfo_to_string(&info->mergeinfo, mergeinfo, pool));
 
@@ -1141,7 +1142,6 @@ wc_to_repos_copy(svn_commit_info_t **com
   void *edit_baton;
   void *commit_baton;
   apr_hash_t *committables;
-  svn_wc_adm_access_t *adm_access;
   apr_array_header_t *commit_items;
   const svn_wc_entry_t *entry;
   apr_pool_t *iterpool;
@@ -1149,15 +1149,13 @@ wc_to_repos_copy(svn_commit_info_t **com
   apr_hash_t *commit_revprops;
   int i;
 
-  /* Find the common root of all the source paths, and probe the wc. */
+  /* Find the common root of all the source paths */
   get_copy_pair_ancestors(copy_pairs, &top_src_path, NULL, NULL, pool);
-  SVN_ERR(svn_wc__adm_probe_in_context(&adm_access, ctx->wc_ctx, top_src_path,
-                                       FALSE, -1, ctx->cancel_func,
-                                       ctx->cancel_baton, pool));
-
-  /* The commit process uses absolute paths, so we need to open the access
-     baton using absolute paths, and so we really need to use absolute
-     paths everywhere. */
+
+  /* Do we need to lock the working copy?  1.6 didn't take a write
+     lock, but what happens if the working copy changes during the copy
+     operation? */
+
   iterpool = svn_pool_create(pool);
 
   for (i = 0; i < copy_pairs->nelts; i++)
@@ -1166,8 +1164,7 @@ wc_to_repos_copy(svn_commit_info_t **com
                                                     svn_client__copy_pair_t *);
       svn_pool_clear(iterpool);
       /* Sanity check if the source path is versioned. */
-      SVN_ERR(svn_dirent_get_absolute(&pair->src_abs, pair->src, pool));
-      SVN_ERR(svn_wc__get_entry_versioned(&entry, ctx->wc_ctx, pair->src_abs,
+      SVN_ERR(svn_wc__get_entry_versioned(&entry, ctx->wc_ctx, pair->src,
                                           svn_node_unknown, FALSE, FALSE,
                                           iterpool, iterpool));
     }
@@ -1193,8 +1190,7 @@ wc_to_repos_copy(svn_commit_info_t **com
     }
 
   SVN_ERR(svn_client__open_ra_session_internal(&ra_session, top_dst_url,
-                                               svn_wc_adm_access_path(
-                                                                 adm_access),
+                                               top_src_path,
                                                NULL, TRUE, TRUE, ctx, pool));
 
   /* If requested, determine the nearest existing parent of the destination,
@@ -1216,7 +1212,7 @@ wc_to_repos_copy(svn_commit_info_t **com
 
       svn_pool_clear(iterpool);
 
-      SVN_ERR(svn_wc__get_entry_versioned(&entry, ctx->wc_ctx, pair->src_abs,
+      SVN_ERR(svn_wc__get_entry_versioned(&entry, ctx->wc_ctx, pair->src,
                                           svn_node_unknown, FALSE, FALSE,
                                           iterpool, iterpool));
       pair->src_revnum = entry->revision;
@@ -1272,7 +1268,7 @@ wc_to_repos_copy(svn_commit_info_t **com
       if (! message)
         {
           svn_pool_destroy(iterpool);
-          return svn_error_return(svn_wc_adm_close2(adm_access, pool));
+          return SVN_NO_ERROR;
         }
     }
   else
@@ -1295,7 +1291,7 @@ wc_to_repos_copy(svn_commit_info_t **com
                                      SVN_CLIENT__SINGLE_REPOS_NAME,
                                      APR_HASH_KEY_STRING)))
     {
-      return svn_error_return(svn_wc_adm_close2(adm_access, pool));
+      return SVN_NO_ERROR;
     }
 
   /* If we are creating intermediate directories, tack them onto the list
@@ -1335,10 +1331,10 @@ wc_to_repos_copy(svn_commit_info_t **com
          info known to the WC and the repository. */
       item->outgoing_prop_changes = apr_array_make(pool, 1,
                                                    sizeof(svn_prop_t *));
-      SVN_ERR(calculate_target_mergeinfo(ra_session, &mergeinfo, adm_access,
-                                         pair->src, pair->src_revnum,
-                                         FALSE, ctx, iterpool));
-      SVN_ERR(svn_wc__get_entry_versioned(&entry, ctx->wc_ctx, pair->src_abs,
+      SVN_ERR(calculate_target_mergeinfo(ra_session, &mergeinfo, pair->src,
+                                         NULL, SVN_INVALID_REVNUM,
+                                         ctx, iterpool));
+      SVN_ERR(svn_wc__get_entry_versioned(&entry, ctx->wc_ctx, pair->src,
                                           svn_node_unknown, FALSE, FALSE,
                                           pool, pool));
       SVN_ERR(svn_client__parse_mergeinfo(&wc_mergeinfo, ctx->wc_ctx,
@@ -1397,8 +1393,7 @@ wc_to_repos_copy(svn_commit_info_t **com
 
   svn_pool_destroy(iterpool);
 
-  /* It's only a read lock, so unlocking is harmless. */
-  return svn_error_return(svn_wc_adm_close2(adm_access, pool));
+  return SVN_NO_ERROR;
 }
 
 /* Peform each individual copy operation for a repos -> wc copy.  A
@@ -1474,7 +1469,7 @@ repos_to_wc_copy_single(svn_client__copy
              ### source path. */
           SVN_ERR(calculate_target_mergeinfo(ra_session, &src_mergeinfo, NULL,
                                              pair->src, src_revnum,
-                                             FALSE, ctx, pool));
+                                             ctx, pool));
           SVN_ERR(extend_wc_mergeinfo(dst_abspath, src_mergeinfo, ctx, pool));
         }
       else  /* different repositories */
@@ -1532,7 +1527,7 @@ repos_to_wc_copy_single(svn_client__copy
 
       SVN_ERR(calculate_target_mergeinfo(ra_session, &src_mergeinfo,
                                          NULL, pair->src, src_revnum,
-                                         FALSE, ctx, pool));
+                                         ctx, pool));
       SVN_ERR(extend_wc_mergeinfo(dst_abspath, src_mergeinfo, ctx, pool));
 
       /* Ideally, svn_wc_add_repos_file3() would take a notify function
@@ -1554,6 +1549,137 @@ repos_to_wc_copy_single(svn_client__copy
   return SVN_NO_ERROR;
 }
 
+static svn_error_t*
+repos_to_wc_copy_locked(const apr_array_header_t *copy_pairs,
+                        const char *top_dst_path,
+                        svn_boolean_t ignore_externals,
+                        svn_ra_session_t *ra_session,
+                        svn_client_ctx_t *ctx,
+                        apr_pool_t *scratch_pool)
+{
+  int i;
+  const char *src_uuid = NULL, *dst_uuid = NULL;
+  svn_boolean_t same_repositories;
+  apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+
+  /* We've already checked for physical obstruction by a working file.
+     But there could also be logical obstruction by an entry whose
+     working file happens to be missing.*/
+  for (i = 0; i < copy_pairs->nelts; i++)
+    {
+      svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
+                                                    svn_client__copy_pair_t *);
+      const svn_wc_entry_t *ent;
+      const char *dst_abspath;
+
+      svn_pool_clear(iterpool);
+      SVN_ERR(svn_dirent_get_absolute(&dst_abspath, pair->dst, iterpool));
+
+      SVN_ERR(svn_wc__maybe_get_entry(&ent, ctx->wc_ctx, dst_abspath,
+                                      svn_node_unknown, TRUE, FALSE,
+                                      iterpool, iterpool));
+      if (ent)
+        {
+          /* TODO(#2843): Rework the error report. Maybe we can simplify the
+             condition. Currently, the first is about hidden items and the
+             second is for missing items. */
+          if (ent->depth == svn_depth_exclude
+              || ent->absent)
+            {
+              return svn_error_createf
+                (SVN_ERR_ENTRY_EXISTS,
+                 NULL, _("'%s' is already under version control"),
+                 svn_dirent_local_style(pair->dst, iterpool));
+            }
+          else if ((ent->kind != svn_node_dir) &&
+                   (ent->schedule != svn_wc_schedule_delete)
+                   && ! ent->deleted)
+            return svn_error_createf
+              (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
+               _("Entry for '%s' exists (though the working file is missing)"),
+               svn_dirent_local_style(pair->dst, iterpool));
+        }
+    }
+
+  /* Decide whether the two repositories are the same or not. */
+  {
+    svn_error_t *src_err, *dst_err;
+    const char *parent;
+    const char *parent_abspath;
+
+    /* Get the repository uuid of SRC_URL */
+    src_err = svn_ra_get_uuid2(ra_session, &src_uuid, scratch_pool);
+    if (src_err && src_err->apr_err != SVN_ERR_RA_NO_REPOS_UUID)
+      return svn_error_return(src_err);
+
+    /* Get repository uuid of dst's parent directory, since dst may
+       not exist.  ### TODO:  we should probably walk up the wc here,
+       in case the parent dir has an imaginary URL.  */
+    if (copy_pairs->nelts == 1)
+      parent = svn_dirent_dirname(top_dst_path, scratch_pool);
+    else
+      parent = top_dst_path;
+
+    SVN_ERR(svn_dirent_get_absolute(&parent_abspath, parent, scratch_pool));
+    dst_err = svn_client_uuid_from_path2(&dst_uuid, parent_abspath, ctx,
+                                         scratch_pool, scratch_pool);
+    if (dst_err && dst_err->apr_err != SVN_ERR_RA_NO_REPOS_UUID)
+      return dst_err;
+
+    /* If either of the UUIDs are nonexistent, then at least one of
+       the repositories must be very old.  Rather than punish the
+       user, just assume the repositories are different, so no
+       copy-history is attempted. */
+    if (src_err || dst_err || (! src_uuid) || (! dst_uuid))
+      same_repositories = FALSE;
+
+    else
+      same_repositories = (strcmp(src_uuid, dst_uuid) == 0);
+  }
+
+  /* Perform the move for each of the copy_pairs. */
+  for (i = 0; i < copy_pairs->nelts; i++)
+    {
+      /* Check for cancellation */
+      if (ctx->cancel_func)
+        SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(repos_to_wc_copy_single(APR_ARRAY_IDX(copy_pairs, i,
+                                                    svn_client__copy_pair_t *),
+                                      same_repositories,
+                                      ignore_externals,
+                                      ra_session, ctx, iterpool));
+    }
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+struct repos_to_wc_copy_baton {
+  const apr_array_header_t *copy_pairs;
+  const char *top_dst_path;
+  svn_boolean_t ignore_externals;
+  svn_ra_session_t *ra_session;
+  svn_client_ctx_t *ctx;
+};
+
+/* Implements svn_wc__with_write_lock_func_t. */
+static svn_error_t *
+repos_to_wc_copy_cb(void *baton,
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool)
+{
+  struct repos_to_wc_copy_baton *b = baton;
+
+  SVN_ERR(repos_to_wc_copy_locked(b->copy_pairs, b->top_dst_path,
+                                  b->ignore_externals, b->ra_session,
+                                  b->ctx, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 repos_to_wc_copy(const apr_array_header_t *copy_pairs,
                  svn_boolean_t make_parents,
@@ -1562,11 +1688,10 @@ repos_to_wc_copy(const apr_array_header_
                  apr_pool_t *pool)
 {
   svn_ra_session_t *ra_session;
-  svn_wc_adm_access_t *adm_access;
   const char *top_src_url, *top_dst_path;
-  const char *src_uuid = NULL, *dst_uuid = NULL;
-  svn_boolean_t same_repositories;
   apr_pool_t *iterpool = svn_pool_create(pool);
+  const char *lock_abspath;
+  struct repos_to_wc_copy_baton baton;
   int i;
 
   /* Get the real path for the source, based upon its peg revision. */
@@ -1594,8 +1719,16 @@ repos_to_wc_copy(const apr_array_header_
     }
 
   get_copy_pair_ancestors(copy_pairs, &top_src_url, &top_dst_path, NULL, pool);
+  lock_abspath = top_dst_path;
   if (copy_pairs->nelts == 1)
-    top_src_url = svn_uri_dirname(top_src_url, pool);
+    {
+      svn_node_kind_t kind;
+      top_src_url = svn_uri_dirname(top_src_url, pool);
+      SVN_ERR(svn_wc__node_get_kind(&kind, ctx->wc_ctx, top_dst_path, FALSE,
+                                    pool));
+      if (kind != svn_node_dir)
+        lock_abspath = svn_dirent_dirname(top_dst_path, pool);
+    }
 
   /* Open a repository session to the longest common src ancestor.  We do not
      (yet) have a working copy, so we don't have a corresponding path and
@@ -1670,105 +1803,18 @@ repos_to_wc_copy(const apr_array_header_
                                    svn_dirent_local_style(dst_parent, pool));
         }
     }
+  svn_pool_destroy(iterpool);
 
-  /* Probe the wc at the longest common dst ancestor. */
-  SVN_ERR(svn_wc__adm_probe_in_context(&adm_access, ctx->wc_ctx, top_dst_path,
-                                       TRUE, -1, ctx->cancel_func,
-                                       ctx->cancel_baton, pool));
-
-  /* We've already checked for physical obstruction by a working file.
-     But there could also be logical obstruction by an entry whose
-     working file happens to be missing.*/
-  for (i = 0; i < copy_pairs->nelts; i++)
-    {
-      svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
-                                                    svn_client__copy_pair_t *);
-      const svn_wc_entry_t *ent;
-      const char *dst_abspath;
-
-      svn_pool_clear(iterpool);
-      SVN_ERR(svn_dirent_get_absolute(&dst_abspath, pair->dst, iterpool));
-
-      SVN_ERR(svn_wc__maybe_get_entry(&ent, ctx->wc_ctx, dst_abspath,
-                                      svn_node_unknown, TRUE, FALSE,
-                                      iterpool, iterpool));
-      if (ent)
-        {
-          /* TODO(#2843): Rework the error report. Maybe we can simplify the
-             condition. Currently, the first is about hidden items and the
-             second is for missing items. */
-          if (ent->depth == svn_depth_exclude
-              || ent->absent)
-            {
-              return svn_error_createf
-                (SVN_ERR_ENTRY_EXISTS,
-                 NULL, _("'%s' is already under version control"),
-                 svn_dirent_local_style(pair->dst, pool));
-            }
-          else if ((ent->kind != svn_node_dir) &&
-                   (ent->schedule != svn_wc_schedule_delete)
-                   && ! ent->deleted)
-            return svn_error_createf
-              (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
-               _("Entry for '%s' exists (though the working file is missing)"),
-               svn_dirent_local_style(pair->dst, pool));
-        }
-    }
-
-  /* Decide whether the two repositories are the same or not. */
-  {
-    svn_error_t *src_err, *dst_err;
-    const char *parent;
-    const char *parent_abspath;
-
-    /* Get the repository uuid of SRC_URL */
-    src_err = svn_ra_get_uuid2(ra_session, &src_uuid, pool);
-    if (src_err && src_err->apr_err != SVN_ERR_RA_NO_REPOS_UUID)
-      return svn_error_return(src_err);
-
-    /* Get repository uuid of dst's parent directory, since dst may
-       not exist.  ### TODO:  we should probably walk up the wc here,
-       in case the parent dir has an imaginary URL.  */
-    if (copy_pairs->nelts == 1)
-      parent = svn_dirent_dirname(top_dst_path, pool);
-    else
-      parent = top_dst_path;
-
-    SVN_ERR(svn_dirent_get_absolute(&parent_abspath, parent, pool));
-    dst_err = svn_client_uuid_from_path2(&dst_uuid, parent_abspath, ctx, pool,
-                                         pool);
-    if (dst_err && dst_err->apr_err != SVN_ERR_RA_NO_REPOS_UUID)
-      return dst_err;
-
-    /* If either of the UUIDs are nonexistent, then at least one of
-       the repositories must be very old.  Rather than punish the
-       user, just assume the repositories are different, so no
-       copy-history is attempted. */
-    if (src_err || dst_err || (! src_uuid) || (! dst_uuid))
-      same_repositories = FALSE;
-
-    else
-      same_repositories = (strcmp(src_uuid, dst_uuid) == 0);
-  }
-
-  /* Perform the move for each of the copy_pairs. */
-  for (i = 0; i < copy_pairs->nelts; i++)
-    {
-      /* Check for cancellation */
-      if (ctx->cancel_func)
-        SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
-
-      svn_pool_clear(iterpool);
+  baton.copy_pairs = copy_pairs;
+  baton.top_dst_path = top_dst_path;
+  baton.ignore_externals = ignore_externals;
+  baton.ra_session = ra_session;
+  baton.ctx = ctx;
 
-      SVN_ERR(repos_to_wc_copy_single(APR_ARRAY_IDX(copy_pairs, i,
-                                                    svn_client__copy_pair_t *),
-                                      same_repositories,
-                                      ignore_externals,
-                                      ra_session, ctx, iterpool));
-    }
-
-  svn_pool_destroy(iterpool);
-  return svn_error_return(svn_wc_adm_close2(adm_access, pool));
+  SVN_ERR(svn_wc__call_with_write_lock(repos_to_wc_copy_cb, &baton,
+                                       ctx->wc_ctx, lock_abspath,
+                                       pool, pool));
+  return SVN_NO_ERROR;
 }
 
 #define NEED_REPOS_REVNUM(revision) \
@@ -1800,6 +1846,8 @@ try_copy(svn_commit_info_t **commit_info
   srcs_are_urls = svn_path_is_url(APR_ARRAY_IDX(sources, 0,
                                   svn_client_copy_source_t *)->path);
   dst_is_url = svn_path_is_url(dst_path_in);
+  if (!dst_is_url)
+    SVN_ERR(svn_dirent_get_absolute(&dst_path_in, dst_path_in, pool));
 
   /* If we have multiple source paths, it implies the dst_path is a
      directory we are moving or copying into.  Populate the COPY_PAIRS
@@ -1818,7 +1866,10 @@ try_copy(svn_commit_info_t **commit_info
 
           svn_pool_clear(iterpool);
 
-          pair->src = apr_pstrdup(pool, source->path);
+          if (src_is_url)
+            pair->src = apr_pstrdup(pool, source->path);
+          else
+            SVN_ERR(svn_dirent_get_absolute(&pair->src, source->path, pool));
           pair->src_op_revision = *source->revision;
           pair->src_peg_revision = *source->peg_revision;
 
@@ -1853,8 +1904,12 @@ try_copy(svn_commit_info_t **commit_info
       svn_client__copy_pair_t *pair = apr_palloc(pool, sizeof(*pair));
       svn_client_copy_source_t *source =
         APR_ARRAY_IDX(sources, 0, svn_client_copy_source_t *);
+      svn_boolean_t src_is_url = svn_path_is_url(source->path);
 
-      pair->src = apr_pstrdup(pool, source->path);
+      if (src_is_url)
+        pair->src = apr_pstrdup(pool, source->path);
+      else
+        SVN_ERR(svn_dirent_get_absolute(&pair->src, source->path, pool));
       pair->src_op_revision = *source->revision;
       pair->src_peg_revision = *source->peg_revision;
 
@@ -2072,7 +2127,7 @@ try_copy(svn_commit_info_t **commit_info
 /* Public Interfaces */
 svn_error_t *
 svn_client_copy5(svn_commit_info_t **commit_info_p,
-                 apr_array_header_t *sources,
+                 const apr_array_header_t *sources,
                  const char *dst_path,
                  svn_boolean_t copy_as_child,
                  svn_boolean_t make_parents,
@@ -2148,7 +2203,7 @@ svn_client_copy5(svn_commit_info_t **com
 
 svn_error_t *
 svn_client_move5(svn_commit_info_t **commit_info_p,
-                 apr_array_header_t *src_paths,
+                 const apr_array_header_t *src_paths,
                  const char *dst_path,
                  svn_boolean_t force,
                  svn_boolean_t move_as_child,

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/delete.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/delete.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/delete.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/delete.c Tue Aug 10 18:06:17 2010
@@ -287,6 +287,30 @@ svn_client__wc_delete(const char *path,
   return SVN_NO_ERROR;
 }
 
+/* Callback baton for delete_with_write_lock_baton. */
+struct delete_with_write_lock_baton
+{
+  const char *path;
+  svn_boolean_t force;
+  svn_boolean_t keep_local;
+  svn_client_ctx_t *ctx;
+};
+
+/* Implements svn_wc__with_write_lock_func_t. */
+static svn_error_t *
+delete_with_write_lock_func(void *baton,
+                            apr_pool_t *result_pool,
+                            apr_pool_t *scratch_pool)
+{
+  struct delete_with_write_lock_baton *args = baton;
+
+  /* Let the working copy library handle the PATH. */
+  return svn_client__wc_delete(args->path, args->force,
+                               FALSE, args->keep_local,
+                               args->ctx->notify_func2,
+                               args->ctx->notify_baton2,
+                               args->ctx, scratch_pool);
+}
 
 svn_error_t *
 svn_client_delete3(svn_commit_info_t **commit_info_p,
@@ -311,28 +335,24 @@ svn_client_delete3(svn_commit_info_t **c
 
       for (i = 0; i < paths->nelts; i++)
         {
-          svn_wc_adm_access_t *adm_access;
+          struct delete_with_write_lock_baton dwwlb;
           const char *path = APR_ARRAY_IDX(paths, i, const char *);
-          const char *parent_path;
+          const char *local_abspath;
 
           svn_pool_clear(subpool);
-          parent_path = svn_dirent_dirname(path, subpool);
 
           /* See if the user wants us to stop. */
           if (ctx->cancel_func)
             SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
 
-          /* Let the working copy library handle the PATH. */
-          SVN_ERR(svn_wc__adm_open_in_context(&adm_access, ctx->wc_ctx,
-                                              parent_path, TRUE, -1,
-                                              ctx->cancel_func,
-                                              ctx->cancel_baton, subpool));
-          SVN_ERR(svn_client__wc_delete(path, force,
-                                        FALSE, keep_local,
-                                        ctx->notify_func2,
-                                        ctx->notify_baton2,
-                                        ctx, subpool));
-          SVN_ERR(svn_wc_adm_close2(adm_access, subpool));
+          SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, subpool));
+          dwwlb.path = path;
+          dwwlb.force = force;
+          dwwlb.keep_local = keep_local;
+          dwwlb.ctx = ctx;
+          SVN_ERR(svn_wc__call_with_write_lock(delete_with_write_lock_func,
+                                               &dwwlb, ctx->wc_ctx,
+                                               local_abspath, pool, subpool));
         }
       svn_pool_destroy(subpool);
     }

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/deprecated.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/deprecated.c Tue Aug 10 18:06:17 2010
@@ -412,7 +412,7 @@ svn_client_commit(svn_client_commit_info
 
 svn_error_t *
 svn_client_copy4(svn_commit_info_t **commit_info_p,
-                 apr_array_header_t *sources,
+                 const apr_array_header_t *sources,
                  const char *dst_path,
                  svn_boolean_t copy_as_child,
                  svn_boolean_t make_parents,
@@ -1653,7 +1653,7 @@ svn_client_switch(svn_revnum_t *result_r
   svn_opt_revision_t peg_revision;
   peg_revision.kind = svn_opt_revision_unspecified;
   return svn_client__switch_internal(result_rev, path, switch_url,
-                                     &peg_revision, revision, NULL,
+                                     &peg_revision, revision,
                                      SVN_DEPTH_INFINITY_OR_FILES(recurse),
                                      FALSE, NULL, FALSE, FALSE, FALSE, ctx,
                                      pool);
@@ -1862,7 +1862,7 @@ svn_client_mergeinfo_log_merged(const ch
                                 svn_client_ctx_t *ctx,
                                 apr_pool_t *pool)
 {
-  return svn_client_mergeinfo_log(path_or_url, TRUE, peg_revision,
+  return svn_client_mergeinfo_log(TRUE, path_or_url, peg_revision,
                                   merge_source_path_or_url,
                                   src_peg_revision,
                                   log_receiver, log_receiver_baton,
@@ -1883,7 +1883,7 @@ svn_client_mergeinfo_log_eligible(const 
                                   svn_client_ctx_t *ctx,
                                   apr_pool_t *pool)
 {
-  return svn_client_mergeinfo_log(path_or_url, FALSE, peg_revision,
+  return svn_client_mergeinfo_log(FALSE, path_or_url, peg_revision,
                                   merge_source_path_or_url,
                                   src_peg_revision,
                                   log_receiver, log_receiver_baton,

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/diff.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/diff.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/diff.c Tue Aug 10 18:06:17 2010
@@ -126,8 +126,8 @@ display_mergeinfo_diff(const char *old_m
   for (hi = apr_hash_first(pool, deleted);
        hi; hi = apr_hash_next(hi))
     {
-      const char *from_path = svn_apr_hash_index_key(hi);
-      apr_array_header_t *merge_revarray = svn_apr_hash_index_val(hi);
+      const char *from_path = svn__apr_hash_index_key(hi);
+      apr_array_header_t *merge_revarray = svn__apr_hash_index_val(hi);
       svn_string_t *merge_revstr;
 
       SVN_ERR(svn_rangelist_to_string(&merge_revstr, merge_revarray, pool));
@@ -141,8 +141,8 @@ display_mergeinfo_diff(const char *old_m
   for (hi = apr_hash_first(pool, added);
        hi; hi = apr_hash_next(hi))
     {
-      const char *from_path = svn_apr_hash_index_key(hi);
-      apr_array_header_t *merge_revarray = svn_apr_hash_index_val(hi);
+      const char *from_path = svn__apr_hash_index_key(hi);
+      apr_array_header_t *merge_revarray = svn__apr_hash_index_val(hi);
       svn_string_t *merge_revstr;
 
       SVN_ERR(svn_rangelist_to_string(&merge_revstr, merge_revarray, pool));
@@ -1299,7 +1299,7 @@ diff_repos_repos(const struct diff_param
      Otherwise, we just use "". */
   SVN_ERR(svn_client__get_diff_editor
           (drr.base_path ? drr.base_path : "",
-           ctx->wc_ctx, callbacks, callback_baton, diff_param->depth,
+           NULL, callbacks, callback_baton, diff_param->depth,
            FALSE /* doesn't matter for diff */, extra_ra_session, drr.rev1,
            NULL /* no notify_func */, NULL /* no notify_baton */,
            ctx->cancel_func, ctx->cancel_baton,

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/export.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/export.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/export.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/export.c Tue Aug 10 18:06:17 2010
@@ -128,23 +128,43 @@ copy_one_versioned_file(const char *from
   else if (err)
     return svn_error_return(err);
 
-  /* Only export 'added' files when the revision is WORKING.
-     Otherwise, skip the 'added' files, since they didn't exist
-     in the BASE revision and don't have an associated text-base.
-
-     Don't export 'deleted' files and directories unless it's a
+  /* Don't export 'deleted' files and directories unless it's a
      revision other than WORKING.  These files and directories
      don't really exist in WORKING. */
-  if ((revision->kind != svn_opt_revision_working &&
-       entry->schedule == svn_wc_schedule_add) ||
-      (revision->kind == svn_opt_revision_working &&
-       entry->schedule == svn_wc_schedule_delete))
+  if (revision->kind == svn_opt_revision_working
+      && entry->schedule == svn_wc_schedule_delete)
     return SVN_NO_ERROR;
 
   if (revision->kind != svn_opt_revision_working)
     {
+      /* Only export 'added' files when the revision is WORKING. This is not
+         WORKING, so skip the 'added' files, since they didn't exist
+         in the BASE revision and don't have an associated text-base.
+         
+         'replaced' files are technically the same as 'added' files.
+         ### TODO: Handle replaced nodes properly.
+         ###       svn_opt_revision_base refers to the "new" 
+         ###       base of the node. That means, if a node is locally
+         ###       replaced, export skips this node, as if it was locally
+         ###       added, because svn_opt_revision_base refers to the base
+         ###       of the added node, not to the node that was deleted.
+         ###       In contrast, when the node is copied-here or moved-here,
+         ###       the copy/move source's content will be exported.
+         ###       It is currently not possible to export the revert-base
+         ###       when a node is locally replaced. We need a new
+         ###       svn_opt_revision_ enum value for proper distinction
+         ###       between revert-base and commit-base.
+
+         Copied-/moved-here nodes have a base, so export both added and
+         replaced files when they involve a copy-/move-here.
+
+         We get all this for free from evaluating SOURCE == NULL:
+       */
       SVN_ERR(svn_wc_get_pristine_contents2(&source, wc_ctx, from_abspath,
                                             scratch_pool, scratch_pool));
+      if (source == NULL)
+        return SVN_NO_ERROR;
+
       SVN_ERR(svn_wc_get_prop_diffs2(NULL, &props, wc_ctx, from_abspath,
                                      scratch_pool, scratch_pool));
     }
@@ -294,15 +314,23 @@ copy_versioned_files(const char *from,
                                       svn_node_unknown, FALSE, FALSE,
                                       pool, pool));
 
-  /* Only export 'added' files when the revision is WORKING.
-     Otherwise, skip the 'added' files, since they didn't exist
-     in the BASE revision and don't have an associated text-base.
+  /* Only export 'added' and 'replaced' files when the revision is WORKING;
+     when the revision is BASE (i.e. != WORKING), only export 'added' and
+     'replaced' files when they are part of a copy-/move-here. Otherwise, skip
+     them, since they don't have an associated text-base. This condition for
+     added/replaced simply is an optimization. Added and replaced files would
+     be handled similarly by svn_wc_get_pristine_contents2(), which would
+     return NULL if they have no base associated.
+     TODO: We may prefer not to duplicate this condition and rather use
+     svn_wc_get_pristine_contents2() or a dedicated new function instead.
 
      Don't export 'deleted' files and directories unless it's a
      revision other than WORKING.  These files and directories
      don't really exist in WORKING. */
-  if ((revision->kind != svn_opt_revision_working &&
-       entry->schedule == svn_wc_schedule_add) ||
+  if ((revision->kind != svn_opt_revision_working
+       && (entry->schedule == svn_wc_schedule_add
+           || entry->schedule == svn_wc_schedule_replace)
+       && !entry->copied) ||
       (revision->kind == svn_opt_revision_working &&
        entry->schedule == svn_wc_schedule_delete))
     return SVN_NO_ERROR;
@@ -464,7 +492,7 @@ copy_versioned_files(const char *from,
  * Create PATH if it does not exist and is not obstructed, and invoke
  * NOTIFY_FUNC with NOTIFY_BATON on PATH.
  *
- * If PATH exists but is a file, then error with SVN_ERR_WC_NOT_DIRECTORY.
+ * If PATH exists but is a file, then error with SVN_ERR_WC_NOT_WORKING_COPY.
  *
  * If PATH is a already a directory, then error with
  * SVN_ERR_WC_OBSTRUCTED_UPDATE, unless FORCE, in which case just
@@ -960,8 +988,8 @@ svn_client_export5(svn_revnum_t *result_
            * with information. */
           for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi))
             {
-              const char *propname = svn_apr_hash_index_key(hi);
-              const svn_string_t *propval = svn_apr_hash_index_val(hi);
+              const char *propname = svn__apr_hash_index_key(hi);
+              const svn_string_t *propval = svn__apr_hash_index_val(hi);
 
               SVN_ERR(change_file_prop(fb, propname, propval, pool));
             }

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/externals.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/externals.c Tue Aug 10 18:06:17 2010
@@ -53,10 +53,6 @@ struct handle_external_item_change_baton
   /* The directory that has this externals property. */
   const char *parent_dir;
 
-  /* Access baton for parent_dir.  If the external is an export, this
-     this must be NULL, otherwise it must be non-NULL. */
-  svn_wc_adm_access_t *adm_access;
-
   /* The URL for the directory that has this externals property. */
   const char *parent_dir_url;
 
@@ -80,41 +76,37 @@ struct handle_external_item_change_baton
 };
 
 
-/* Remove the directory at PATH from revision control, and do the same
- * to any revision controlled directories underneath PATH (including
- * directories not referred to by parent svn administrative areas);
- * then if PATH is empty afterwards, remove it, else rename it to a
+struct relegate_dir_external_with_write_lock_baton {
+  const char *local_abspath;
+  svn_wc_context_t *wc_ctx;
+  svn_cancel_func_t cancel_func;
+  void *cancel_baton;
+};
+
+/* Note: All arguments are in the baton above.
+ *
+ * Remove the directory at LOCAL_ABSPATH from revision control, and do the
+ * same to any revision controlled directories underneath LOCAL_ABSPATH
+ * (including directories not referred to by parent svn administrative areas);
+ * then if LOCAL_ABSPATH is empty afterwards, remove it, else rename it to a
  * unique name in the same parent directory.
  *
  * Pass CANCEL_FUNC, CANCEL_BATON to svn_wc_remove_from_revision_control.
  *
- * Use POOL for all temporary allocation.
- *
- * Note: this function is not passed a svn_wc_adm_access_t.  Instead,
- * it separately opens the object being deleted, so that if there is a
- * lock on that object, the object cannot be deleted.
+ * Use SCRATCH_POOL for all temporary allocation.
  */
 static svn_error_t *
-relegate_dir_external(const char *path,
-                      svn_wc_context_t *wc_ctx,
-                      svn_cancel_func_t cancel_func,
-                      void *cancel_baton,
-                      apr_pool_t *pool)
+relegate_dir_external(void *baton,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
 {
+  struct relegate_dir_external_with_write_lock_baton *b = baton;
   svn_error_t *err = SVN_NO_ERROR;
-  const char *local_abspath;
 
-  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
-  SVN_ERR(svn_wc__acquire_write_lock(NULL, wc_ctx, local_abspath, NULL, pool));
-  err = svn_wc_remove_from_revision_control2(wc_ctx, local_abspath,
+  err = svn_wc_remove_from_revision_control2(b->wc_ctx, b->local_abspath,
                                              TRUE, FALSE,
-                                             cancel_func, cancel_baton,
-                                             pool);
-
-  /* ### Ugly. Unlock only if not going to return an error. Revisit */
-  if (!err || err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD)
-    SVN_ERR(svn_wc__release_write_lock(wc_ctx, local_abspath, pool));
-
+                                             b->cancel_func, b->cancel_baton,
+                                             scratch_pool);
   if (err && (err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
     {
       const char *parent_dir;
@@ -124,12 +116,13 @@ relegate_dir_external(const char *path,
       svn_error_clear(err);
       err = SVN_NO_ERROR;
 
-      svn_dirent_split(path, &parent_dir, &dirname, pool);
+      svn_dirent_split(b->local_abspath, &parent_dir, &dirname, scratch_pool);
 
       /* Reserve the new dir name. */
       SVN_ERR(svn_io_open_uniquely_named(NULL, &new_path,
                                          parent_dir, dirname, ".OLD",
-                                         svn_io_file_del_none, pool, pool));
+                                         svn_io_file_del_none,
+                                         scratch_pool, scratch_pool));
 
       /* Sigh...  We must fall ever so slightly from grace.
 
@@ -150,10 +143,10 @@ relegate_dir_external(const char *path,
          no big deal.
       */
       /* Do our best, but no biggy if it fails. The rename will fail. */
-      svn_error_clear(svn_io_remove_file2(new_path, TRUE, pool));
+      svn_error_clear(svn_io_remove_file2(new_path, TRUE, scratch_pool));
 
       /* Rename. */
-      SVN_ERR(svn_io_file_rename(path, new_path, pool));
+      SVN_ERR(svn_io_file_rename(b->local_abspath, new_path, scratch_pool));
     }
 
   return svn_error_return(err);
@@ -238,7 +231,7 @@ switch_dir_external(const char *path,
 
               SVN_ERR(svn_client__switch_internal(NULL, path, url,
                                                   peg_revision, revision,
-                                                  NULL, svn_depth_infinity,
+                                                  svn_depth_infinity,
                                                   TRUE, timestamp_sleep,
                                                   FALSE, FALSE, TRUE, ctx,
                                                   subpool));
@@ -258,12 +251,21 @@ switch_dir_external(const char *path,
   svn_pool_destroy(subpool);
 
   if (kind == svn_node_dir)
-    /* Buh-bye, old and busted ... */
-    SVN_ERR(relegate_dir_external(path,
-                                  ctx->wc_ctx,
-                                  ctx->cancel_func,
-                                  ctx->cancel_baton,
-                                  pool));
+    {
+      struct relegate_dir_external_with_write_lock_baton baton;
+
+      SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
+
+      baton.local_abspath = local_abspath;
+      baton.wc_ctx = ctx->wc_ctx;
+      baton.cancel_func = ctx->cancel_func;
+      baton.cancel_baton = ctx->cancel_baton;
+
+      /* Buh-bye, old and busted ... */
+      SVN_ERR(svn_wc__call_with_write_lock(relegate_dir_external, &baton,
+                                           ctx->wc_ctx, local_abspath,
+                                           pool, pool));
+    }
   else
     {
       /* The target dir might have multiple components.  Guarantee
@@ -287,7 +289,6 @@ switch_file_external(const char *path,
                      const char *url,
                      const svn_opt_revision_t *peg_revision,
                      const svn_opt_revision_t *revision,
-                     svn_wc_adm_access_t *adm_access,
                      svn_ra_session_t *ra_session,
                      const char *ra_session_url,
                      svn_revnum_t ra_revnum,
@@ -297,7 +298,6 @@ switch_file_external(const char *path,
                      apr_pool_t *pool)
 {
   apr_pool_t *subpool = svn_pool_create(pool);
-  svn_wc_adm_access_t *target_adm_access;
   const char *anchor;
   const char *anchor_abspath;
   const char *local_abspath;
@@ -310,9 +310,14 @@ switch_file_external(const char *path,
   svn_boolean_t unlink_file = FALSE;
   svn_boolean_t revert_file = FALSE;
   svn_boolean_t remove_from_revision_control = FALSE;
-  svn_boolean_t close_adm_access = FALSE;
+  svn_boolean_t locked_here;
   svn_error_t *err = NULL;
 
+  /* See if the user wants last-commit timestamps instead of current ones. */
+  SVN_ERR(svn_config_get_bool(cfg, &use_commit_times,
+                              SVN_CONFIG_SECTION_MISCELLANY,
+                              SVN_CONFIG_OPTION_USE_COMMIT_TIMES, FALSE));
+
   /* There must be a working copy to place the file external into. */
   SVN_ERR(svn_wc_get_actual_target2(&anchor, &target, ctx->wc_ctx, path,
                                     subpool, subpool));
@@ -323,52 +328,42 @@ switch_file_external(const char *path,
      baton.  If this fails and returns SVN_ERR_WC_NOT_LOCKED, then try
      to get a new access baton to support inserting a file external
      into a directory external. */
-  err = svn_wc_adm_retrieve(&target_adm_access, adm_access, anchor, subpool);
-  if (err)
-    {
-      if (err->apr_err == SVN_ERR_WC_NOT_LOCKED)
-        {
-          const char *dest_wc_repos_root_url;
-          svn_opt_revision_t peg_rev;
+  SVN_ERR(svn_wc_locked2(&locked_here, NULL, ctx->wc_ctx, anchor_abspath,
+                         subpool));
+  if (!locked_here)
+    {
+      const char *dest_wc_repos_root_url;
+      svn_opt_revision_t peg_rev;
+
+      /* Check that the repository root URL for the newly opened
+         wc is the same as the file external. */
+      peg_rev.kind = svn_opt_revision_base;
+      SVN_ERR(svn_client__get_repos_root(&dest_wc_repos_root_url,
+                                         anchor_abspath, &peg_rev,
+                                         ctx, subpool, subpool));
 
-          svn_error_clear(err);
-          close_adm_access = TRUE;
-          SVN_ERR(svn_wc__adm_open_in_context(&target_adm_access, ctx->wc_ctx,
-                                              anchor, TRUE, -1,
-                                              ctx->cancel_func,
-                                              ctx->cancel_baton, subpool));
-
-          /* Check that the repository root URL for the newly opened
-             wc is the same as the file external. */
-          peg_rev.kind = svn_opt_revision_base;
-          SVN_ERR(svn_client__get_repos_root(&dest_wc_repos_root_url,
-                                             anchor_abspath, &peg_rev,
-                                             ctx, subpool, subpool));
-
-          if (0 != strcmp(repos_root_url, dest_wc_repos_root_url))
-            return svn_error_createf
-              (SVN_ERR_RA_REPOS_ROOT_URL_MISMATCH, NULL,
-               _("Cannot insert a file external from '%s' into a working "
-                 "copy from a different repository rooted at '%s'"),
-               url, dest_wc_repos_root_url);
-        }
-      else
-        return svn_error_return(err);
+      if (0 != strcmp(repos_root_url, dest_wc_repos_root_url))
+        return svn_error_createf
+          (SVN_ERR_RA_REPOS_ROOT_URL_MISMATCH, NULL,
+           _("Cannot insert a file external from '%s' into a working "
+             "copy from a different repository rooted at '%s'"),
+           url, dest_wc_repos_root_url);
+
+      SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx, anchor_abspath,
+                                         subpool, subpool));
     }
 
-  SVN_ERR(svn_wc__maybe_get_entry(&entry, ctx->wc_ctx, local_abspath,
-                                  svn_node_unknown, FALSE, FALSE, subpool,
-                                  subpool));
+  err = svn_wc__maybe_get_entry(&entry, ctx->wc_ctx, local_abspath,
+                                svn_node_unknown, FALSE, FALSE, subpool,
+                                subpool);
+  if (err)
+    goto cleanup;
+
 
   /* Only one notification is done for the external, so don't notify
      for any following steps.  Use the following trick to add the file
      then switch it to the external URL. */
 
-  /* See if the user wants last-commit timestamps instead of current ones. */
-  SVN_ERR(svn_config_get_bool(cfg, &use_commit_times,
-                              SVN_CONFIG_SECTION_MISCELLANY,
-                              SVN_CONFIG_OPTION_USE_COMMIT_TIMES, FALSE));
-
   /* If there is a versioned item with this name, ensure it's a file
      external before working with it.  If there is no entry in the
      working copy, then create an empty file and add it to the working
@@ -377,8 +372,9 @@ switch_file_external(const char *path,
     {
       if (! entry->file_external_path)
         {
-          if (close_adm_access)
-            SVN_ERR(svn_wc_adm_close2(target_adm_access, subpool));
+          if (!locked_here)
+            SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath,
+                                               subpool));
 
           return svn_error_createf
             (SVN_ERR_CLIENT_FILE_EXTERNAL_OVERWRITE_VERSIONED, 0,
@@ -399,9 +395,12 @@ switch_file_external(const char *path,
          conflict on the directory.  To prevent resolving a conflict
          due to another change on the directory, do not allow a file
          external to be added when one exists. */
-      SVN_ERR(svn_wc_conflicted_p3(&text_conflicted, &prop_conflicted,
-                                   &tree_conflicted, ctx->wc_ctx,
-                                   anchor_abspath, subpool));
+      err = svn_wc_conflicted_p3(&text_conflicted, &prop_conflicted,
+                                 &tree_conflicted, ctx->wc_ctx,
+                                 anchor_abspath, subpool);
+      if (err)
+        goto cleanup;
+
       if (text_conflicted || prop_conflicted || tree_conflicted)
         return svn_error_createf
           (SVN_ERR_WC_FOUND_CONFLICT, 0,
@@ -411,11 +410,14 @@ switch_file_external(const char *path,
 
       /* Try to create an empty file.  If there is a file already
          there, then don't touch it. */
-      SVN_ERR(svn_io_file_open(&f,
-                               local_abspath,
-                               APR_WRITE | APR_CREATE | APR_EXCL,
-                               APR_OS_DEFAULT,
-                               subpool));
+      err = svn_io_file_open(&f,
+                             local_abspath,
+                             APR_WRITE | APR_CREATE | APR_EXCL,
+                             APR_OS_DEFAULT,
+                             subpool);
+      if (err)
+        goto cleanup;
+
       unlink_file = TRUE;
       err = svn_io_file_close(f, pool);
       if (err)
@@ -440,7 +442,7 @@ switch_file_external(const char *path,
     }
 
   err = svn_client__switch_internal(NULL, path, url, peg_revision, revision,
-                                    target_adm_access, svn_depth_empty,
+                                    svn_depth_empty,
                                     FALSE, /* depth_is_sticky */
                                     timestamp_sleep,
                                     TRUE, /* ignore_externals */
@@ -462,8 +464,8 @@ switch_file_external(const char *path,
       remove_from_revision_control = TRUE;
   }
 
-  if (close_adm_access)
-    SVN_ERR(svn_wc_adm_close2(target_adm_access, subpool));
+  if (!locked_here)
+    SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, subpool));
 
   svn_pool_destroy(subpool);
   return SVN_NO_ERROR;
@@ -495,8 +497,9 @@ switch_file_external(const char *path,
   if (unlink_file)
     svn_error_clear(svn_io_remove_file2(path, TRUE, subpool));
 
-  if (close_adm_access)
-    SVN_ERR(svn_wc_adm_close2(target_adm_access, subpool));
+  if (!locked_here)
+    svn_error_clear(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath,
+                                               subpool));
 
   svn_pool_destroy(subpool);
   return svn_error_return(err);
@@ -871,7 +874,6 @@ handle_external_item_change(const void *
                                          new_item->url,
                                          &new_item->peg_revision,
                                          &new_item->revision,
-                                         ib->adm_access,
                                          ra_session,
                                          ra_cache.ra_session_url,
                                          ra_cache.ra_revnum,
@@ -895,7 +897,7 @@ handle_external_item_change(const void *
 
       svn_error_t *err;
       const char *remove_target_abspath;
-      svn_boolean_t lock_existed; 
+      svn_boolean_t lock_existed;
 
       SVN_ERR(svn_dirent_get_absolute(&remove_target_abspath,
                                       path,
@@ -907,7 +909,7 @@ handle_external_item_change(const void *
       if (! lock_existed)
         {
           SVN_ERR(svn_wc__acquire_write_lock(NULL, ib->ctx->wc_ctx,
-                                             remove_target_abspath, 
+                                             remove_target_abspath,
                                              ib->iter_pool,
                                              ib->iter_pool));
         }
@@ -939,7 +941,7 @@ handle_external_item_change(const void *
       if (! lock_existed
           && (! err || err->apr_err == SVN_ERR_WC_LEFT_LOCAL_MOD))
         {
-          svn_error_t *err2 = svn_wc__release_write_lock(ib->ctx->wc_ctx, 
+          svn_error_t *err2 = svn_wc__release_write_lock(ib->ctx->wc_ctx,
                                                          remove_target_abspath,
                                                          ib->iter_pool);
           if (err2)
@@ -988,7 +990,6 @@ handle_external_item_change(const void *
                                        new_item->url,
                                        &new_item->peg_revision,
                                        &new_item->revision,
-                                       ib->adm_access,
                                        ra_session,
                                        ra_cache.ra_session_url,
                                        ra_cache.ra_revnum,
@@ -1061,7 +1062,6 @@ struct handle_externals_desc_change_bato
   const char *to_path;
 
   /* Passed through to handle_external_item_change_baton. */
-  svn_wc_adm_access_t *adm_access;
   svn_client_ctx_t *ctx;
   const char *repos_root_url;
   svn_boolean_t *timestamp_sleep;
@@ -1089,11 +1089,9 @@ handle_externals_desc_change(const void 
   svn_wc_external_item2_t *item;
   const char *ambient_depth_w;
   svn_depth_t ambient_depth;
-
-  if (cb->is_export)
-    SVN_ERR_ASSERT(!cb->adm_access);
-  else
-    SVN_ERR_ASSERT(cb->adm_access);
+  const char *url;
+  const char *abs_parent_dir;
+  svn_error_t *err;
 
   if (cb->ambient_depths)
     {
@@ -1159,25 +1157,44 @@ handle_externals_desc_change(const void 
   ib.new_desc          = new_desc_hash;
   ib.parent_dir        = (const char *) key;
   ib.repos_root_url    = cb->repos_root_url;
-  ib.adm_access        = cb->adm_access;
   ib.ctx               = cb->ctx;
   ib.is_export         = cb->is_export;
   ib.timestamp_sleep   = cb->timestamp_sleep;
   ib.pool              = cb->pool;
   ib.iter_pool         = svn_pool_create(cb->pool);
 
-  /* Get the URL of the parent directory by appending a portion of
-     parent_dir to from_url.  from_url is the URL for to_path and
-     to_path is a substring of parent_dir, so append any characters in
-     parent_dir past strlen(to_path) to from_url (making sure to move
-     past a '/' in parent_dir, otherwise svn_path_url_add_component()
-     will error. */
-  len = strlen(cb->to_path);
-  if (ib.parent_dir[len] == '/')
-    ++len;
-  ib.parent_dir_url = svn_path_url_add_component2(cb->from_url,
-                                                  ib.parent_dir + len,
-                                                  cb->pool);
+  SVN_ERR(svn_dirent_get_absolute(&abs_parent_dir, ib.parent_dir,
+                                  cb->pool));
+
+  err = svn_wc__node_get_url(&url, cb->ctx->wc_ctx,
+                             abs_parent_dir, cb->pool, cb->pool);
+
+  /* If we're doing an 'svn export' the current dir will not be a
+     working copy. We can't get the parent_dir. */
+  if (err)
+    {
+      if (err->apr_err == SVN_ERR_WC_NOT_WORKING_COPY ||
+          err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
+        {
+          /* Get the URL of the parent directory by appending a portion of
+             parent_dir to from_url.  from_url is the URL for to_path and
+             to_path is a substring of parent_dir, so append any characters in
+             parent_dir past strlen(to_path) to from_url (making sure to move
+             past a '/' in parent_dir, otherwise svn_path_url_add_component()
+             will error. */
+          len = strlen(cb->to_path);
+          if (ib.parent_dir[len] == '/')
+            ++len;
+          ib.parent_dir_url = svn_path_url_add_component2(cb->from_url,
+                                                          ib.parent_dir + len,
+                                                          cb->pool);
+          svn_error_clear(err);
+        }
+      else
+        return svn_error_return(err);
+    }
+  else
+      ib.parent_dir_url = url;
 
   /* We must use a custom version of svn_hash_diff so that the diff
      entries are processed in the order they were originally specified
@@ -1217,8 +1234,7 @@ handle_externals_desc_change(const void 
 
 
 svn_error_t *
-svn_client__handle_externals(svn_wc_adm_access_t *adm_access,
-                             apr_hash_t *externals_old,
+svn_client__handle_externals(apr_hash_t *externals_old,
                              apr_hash_t *externals_new,
                              apr_hash_t *ambient_depths,
                              const char *from_url,
@@ -1243,7 +1259,6 @@ svn_client__handle_externals(svn_wc_adm_
   cb.from_url          = from_url;
   cb.to_path           = to_path;
   cb.repos_root_url    = repos_root_url;
-  cb.adm_access        = adm_access;
   cb.ctx               = ctx;
   cb.timestamp_sleep   = timestamp_sleep;
   cb.is_export         = FALSE;
@@ -1271,7 +1286,6 @@ svn_client__fetch_externals(apr_hash_t *
   cb.externals_old     = apr_hash_make(pool);
   cb.requested_depth   = requested_depth;
   cb.ambient_depths    = NULL;
-  cb.adm_access        = NULL;
   cb.ctx               = ctx;
   cb.from_url          = from_url;
   cb.to_path           = to_path;
@@ -1308,8 +1322,8 @@ svn_client__do_external_status(apr_hash_
        hi = apr_hash_next(hi))
     {
       apr_array_header_t *exts;
-      const char *path = svn_apr_hash_index_key(hi);
-      const char *propval = svn_apr_hash_index_val(hi);
+      const char *path = svn__apr_hash_index_key(hi);
+      const char *propval = svn__apr_hash_index_val(hi);
       apr_pool_t *iterpool;
       int i;
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/info.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/info.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/info.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/info.c Tue Aug 10 18:06:17 2010
@@ -219,8 +219,8 @@ push_dir_info(svn_ra_session_t *ra_sessi
     {
       const char *path, *URL, *fs_path;
       svn_lock_t *lock;
-      const char *name = svn_apr_hash_index_key(hi);
-      svn_dirent_t *the_ent = svn_apr_hash_index_val(hi);
+      const char *name = svn__apr_hash_index_key(hi);
+      svn_dirent_t *the_ent = svn__apr_hash_index_val(hi);
 
       svn_pool_clear(subpool);
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/locking_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/locking_commands.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/locking_commands.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/locking_commands.c Tue Aug 10 18:06:17 2010
@@ -362,7 +362,7 @@ fetch_tokens(svn_ra_session_t *ra_sessio
 
   for (hi = apr_hash_first(pool, path_tokens); hi; hi = apr_hash_next(hi))
     {
-      const char *path = svn_apr_hash_index_key(hi);
+      const char *path = svn__apr_hash_index_key(hi);
       svn_lock_t *lock;
 
       svn_pool_clear(iterpool);

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/log.c?rev=984153&r1=984152&r2=984153&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/log.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/log.c Tue Aug 10 18:06:17 2010
@@ -322,6 +322,7 @@ svn_client_log5(const apr_array_header_t
   pre_15_receiver_baton_t rb = {0};
   apr_pool_t *iterpool;
   int i;
+  svn_opt_revision_t peg_rev;
 
   if (revision_ranges->nelts == 0)
     {
@@ -330,6 +331,11 @@ svn_client_log5(const apr_array_header_t
          _("Missing required revision specification"));
     }
 
+  /* Make a copy of PEG_REVISION, we may need to change it to a
+     default value. */
+  peg_rev.kind = peg_revision->kind;
+  peg_rev.value = peg_revision->value;
+
   /* Use the passed URL, if there is one.  */
   url_or_path = APR_ARRAY_IDX(targets, 0, const char *);
   session_opt_rev.kind = svn_opt_revision_unspecified;
@@ -358,7 +364,7 @@ svn_client_log5(const apr_array_header_t
           /* Default to any specified peg revision.  Otherwise, if the
            * first target is an URL, then we default to HEAD:0.  Lastly,
            * the default is BASE:0 since WC@HEAD may not exist. */
-          if (peg_revision->kind == svn_opt_revision_unspecified)
+          if (peg_rev.kind == svn_opt_revision_unspecified)
             {
               if (svn_path_is_url(url_or_path))
                 range->start.kind = svn_opt_revision_head;
@@ -366,7 +372,7 @@ svn_client_log5(const apr_array_header_t
                 range->start.kind = svn_opt_revision_base;
             }
           else
-            range->start = *peg_revision;
+            range->start = peg_rev;
 
           if (range->end.kind == svn_opt_revision_unspecified)
             {
@@ -439,6 +445,11 @@ svn_client_log5(const apr_array_header_t
                                 _("When specifying working copy paths, only "
                                   "one target may be given"));
 
+      /* An unspecified PEG_REVISION for a working copy path defautls
+         to svn_opt_revision_working. */
+      if (peg_rev.kind == svn_opt_revision_unspecified)
+          peg_rev.kind = svn_opt_revision_working;
+
       /* Get URLs for each target */
       target_urls = apr_array_make(pool, 1, sizeof(const char *));
       real_targets = apr_array_make(pool, 1, sizeof(const char *));
@@ -486,14 +497,14 @@ svn_client_log5(const apr_array_header_t
     /* If this is a revision type that requires access to the working copy,
      * we use our initial target path to figure out where to root the RA
      * session, otherwise we use our URL. */
-    if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_revision->kind))
+    if (SVN_CLIENT__REVKIND_NEEDS_WC(peg_rev.kind))
       SVN_ERR(svn_path_condense_targets(&ra_target, NULL, targets, TRUE, pool));
     else
       ra_target = url_or_path;
 
     SVN_ERR(svn_client__ra_session_from_path(&ra_session, &ignored_revnum,
                                              &actual_url, ra_target, NULL,
-                                             peg_revision, &session_opt_rev,
+                                             &peg_rev, &session_opt_rev,
                                              ctx, pool));
 
     SVN_ERR(svn_ra_has_capability(ra_session, &has_log_revprops,