You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2010/04/08 17:52:54 UTC

svn commit: r931980 [1/3] - in /subversion/branches/svn-patch-improvements: ./ build/ subversion/include/ subversion/include/private/ subversion/libsvn_client/ subversion/libsvn_diff/ subversion/libsvn_fs_base/ subversion/libsvn_fs_fs/ subversion/libsv...

Author: dannas
Date: Thu Apr  8 15:52:53 2010
New Revision: 931980

URL: http://svn.apache.org/viewvc?rev=931980&view=rev
Log:
Sync svn-patch-improvements branch with trunk.

Modified:
    subversion/branches/svn-patch-improvements/   (props changed)
    subversion/branches/svn-patch-improvements/build/run_tests.py
    subversion/branches/svn-patch-improvements/configure.ac
    subversion/branches/svn-patch-improvements/subversion/include/private/svn_mergeinfo_private.h
    subversion/branches/svn-patch-improvements/subversion/include/svn_fs.h
    subversion/branches/svn-patch-improvements/subversion/include/svn_io.h
    subversion/branches/svn-patch-improvements/subversion/libsvn_client/add.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_client/commit_util.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_client/merge.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_client/mergeinfo.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_diff/parse-diff.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_fs_base/fs.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_fs_fs/fs.h
    subversion/branches/svn-patch-improvements/subversion/libsvn_fs_fs/fs_fs.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_ra_neon/mergeinfo.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_ra_serf/mergeinfo.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_ra_svn/client.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_subr/io.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_subr/mergeinfo.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_files.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_files.h
    subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_ops.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_wc/entries.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_wc/log.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_wc/log.h
    subversion/branches/svn-patch-improvements/subversion/libsvn_wc/props.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_wc/update_editor.c
    subversion/branches/svn-patch-improvements/subversion/libsvn_wc/workqueue.c
    subversion/branches/svn-patch-improvements/subversion/mod_dav_svn/mirror.c
    subversion/branches/svn-patch-improvements/subversion/svnadmin/main.c
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/commit_tests.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/diff_tests.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/externals_tests.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/merge_tests.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/mergeinfo_tests.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/patch_tests.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/svnadmin_tests.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/svndumpfilter_tests.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/svntest/actions.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/svntest/main.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/switch_tests.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/trans_tests.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/update_tests.py
    subversion/branches/svn-patch-improvements/subversion/tests/cmdline/upgrade_tests.py
    subversion/branches/svn-patch-improvements/subversion/tests/libsvn_client/client-test.c
    subversion/branches/svn-patch-improvements/subversion/tests/libsvn_subr/dirent_uri-test.c
    subversion/branches/svn-patch-improvements/subversion/tests/libsvn_subr/mergeinfo-test.c
    subversion/branches/svn-patch-improvements/subversion/tests/svn_test_fs.c
    subversion/branches/svn-patch-improvements/subversion/tests/svn_test_main.c
    subversion/branches/svn-patch-improvements/tools/buildbot/slaves/win32-SharpSvn/   (props changed)
    subversion/branches/svn-patch-improvements/tools/buildbot/slaves/win32-SharpSvn/svn-config.cmd.template
    subversion/branches/svn-patch-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-bindings.cmd
    subversion/branches/svn-patch-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-build-bindings.cmd
    subversion/branches/svn-patch-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-build.cmd
    subversion/branches/svn-patch-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-cleanup.cmd
    subversion/branches/svn-patch-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-template.cmd
    subversion/branches/svn-patch-improvements/tools/buildbot/slaves/win32-SharpSvn/svntest-test.cmd

Propchange: subversion/branches/svn-patch-improvements/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Thu Apr  8 15:52:53 2010
@@ -33,4 +33,4 @@
 /subversion/branches/tc_url_rev:874351-874483
 /subversion/branches/tree-conflicts:868291-873154
 /subversion/branches/tree-conflicts-notify:873926-874008
-/subversion/trunk:918519-930647,931162
+/subversion/trunk:918519-931975

Modified: subversion/branches/svn-patch-improvements/build/run_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/build/run_tests.py?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/build/run_tests.py (original)
+++ subversion/branches/svn-patch-improvements/build/run_tests.py Thu Apr  8 15:52:53 2010
@@ -125,6 +125,10 @@ class TestHarness:
     self._open_log('rb')
     log_lines = self.log.readlines()
 
+    # Remove \r characters introduced by opening the log as binary
+    if sys.platform == 'win32':
+      log_lines = [x.replace('\r', '') for x in log_lines]
+
     # Print the results, from least interesting to most interesting.
 
     # Helper for Work-In-Progress indications for XFAIL tests.

Modified: subversion/branches/svn-patch-improvements/configure.ac
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/configure.ac?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/configure.ac (original)
+++ subversion/branches/svn-patch-improvements/configure.ac Thu Apr  8 15:52:53 2010
@@ -92,7 +92,10 @@ dnl   now generating errors instead of s
 dnl   them.  Only .7 and later can guarantee repository
 dnl   integrity with FSFS.
 
-APR_VER_REGEXES=["0\.9\.[7-9] 0\.9\.1[0-9] 1\."]
+dnl APR 1.4.x is currently broken on OS X; see APR issue 48476 for
+dnl the details.
+
+APR_VER_REGEXES=["0\.9\.[7-9] 0\.9\.1[0-9] 1\.[0-3]\."]
 APU_VER_REGEXES=["0\.9\.[7-9] 0\.9\.1[0-9] 1\."]
 
 SVN_LIB_APR($APR_VER_REGEXES)

Modified: subversion/branches/svn-patch-improvements/subversion/include/private/svn_mergeinfo_private.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/include/private/svn_mergeinfo_private.h?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/include/private/svn_mergeinfo_private.h (original)
+++ subversion/branches/svn-patch-improvements/subversion/include/private/svn_mergeinfo_private.h Thu Apr  8 15:52:53 2010
@@ -85,17 +85,18 @@ svn_boolean_t
 svn_mergeinfo__remove_empty_rangelists(svn_mergeinfo_t mergeinfo,
                                        apr_pool_t *pool);
 
-/* Makes a shallow (ie, mergeinfos are not duped, or altered at all;
-   keys share storage) copy of IN_CATALOG in *OUT_CATALOG.  PREFIX is
-   removed from the beginning of each key in the catalog; it is
-   illegal for any key to not start with PREFIX.  The new hash and
-   temporary values are allocated in POOL.  (This is useful for making
-   the return value from svn_ra_get_mergeinfo relative to the session
-   root, say.) */
+/* Make a shallow (ie, mergeinfos are not duped, or altered at all;
+   keys share storage) copy of IN_CATALOG in *OUT_CATALOG, removing
+   PREFIX_PATH (which is an absolute path) from the beginning of each
+   key in the catalog (each of which is also an absolute path).  It is
+   illegal for any key to not start with PREFIX_PATH.  The new hash
+   and temporary values are allocated in POOL.  (This is useful for
+   making the return value from svn_ra_get_mergeinfo relative to the
+   session root, say.) */
 svn_error_t *
 svn_mergeinfo__remove_prefix_from_catalog(svn_mergeinfo_catalog_t *out_catalog,
                                           svn_mergeinfo_catalog_t in_catalog,
-                                          const char *prefix,
+                                          const char *prefix_path,
                                           apr_pool_t *pool);
 
 /* Makes a deep copy of MERGEINFO in *OUT_MERGEINFO.  If SUFFIX_REL_PATH is

Modified: subversion/branches/svn-patch-improvements/subversion/include/svn_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/include/svn_fs.h?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/include/svn_fs.h (original)
+++ subversion/branches/svn-patch-improvements/subversion/include/svn_fs.h Thu Apr  8 15:52:53 2010
@@ -101,6 +101,13 @@ typedef struct svn_fs_t svn_fs_t;
  * @since New in 1.6.
  */
 #define SVN_FS_CONFIG_PRE_1_6_COMPATIBLE        "pre-1.6-compatible"
+
+/** Create repository format compatible with Subversion versions
+ * earlier than 1.7.
+ *
+ * @since New in 1.7.
+ */
+#define SVN_FS_CONFIG_PRE_1_7_COMPATIBLE        "pre-1.7-compatible"
 /** @} */
 
 

Modified: subversion/branches/svn-patch-improvements/subversion/include/svn_io.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/include/svn_io.h?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/include/svn_io.h (original)
+++ subversion/branches/svn-patch-improvements/subversion/include/svn_io.h Thu Apr  8 15:52:53 2010
@@ -93,8 +93,9 @@ typedef struct svn_io_dirent_t {
  * If @a path exists but is none of the above, set @a *kind to
  * #svn_node_unknown.
  *
- * If unable to determine @a path's kind, return an error, with @a *kind's
- * value undefined.
+ * If @a path is not a valid pathname, set @a *kind to #svn_node_none.  If
+ * unable to determine @a path's kind for any other reason, return an error,
+ * with @a *kind's value undefined.
  *
  * Use @a pool for temporary allocations.
  *

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_client/add.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_client/add.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_client/add.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_client/add.c Thu Apr  8 15:52:53 2010
@@ -560,14 +560,16 @@ add_parent_dirs(svn_client_ctx_t *ctx,
 
   parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool);
 
-  /* ### Do we need locks here?  Are locks being enforced? 1.6 used to
-         acquire and release locks. */
   SVN_ERR(add_parent_dirs(ctx, parent_abspath, scratch_pool));
   SVN_ERR(svn_wc_add4(ctx->wc_ctx, local_abspath, svn_depth_infinity,
                       NULL, SVN_INVALID_REVNUM,
                       ctx->cancel_func, ctx->cancel_baton,
                       ctx->notify_func2, ctx->notify_baton2,
                       scratch_pool));
+  /* ### New dir gets added with its own per-directory lock which we
+     must release.  This code should be redundant when we move to a
+     single db. */
+  SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, local_abspath, scratch_pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_client/commit_util.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_client/commit_util.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_client/commit_util.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_client/commit_util.c Thu Apr  8 15:52:53 2010
@@ -1412,7 +1412,8 @@ do_item_commit(void **dir_baton,
                                  parent_baton, pool);
 
       if (err)
-        return fixup_out_of_date_error(path, item->kind, err);
+        return svn_error_return(fixup_out_of_date_error(path, item->kind,
+                                                        err));
     }
 
   /* If this item is supposed to be added, do so. */
@@ -1471,7 +1472,8 @@ do_item_commit(void **dir_baton,
                                       file_pool, &file_baton);
 
               if (err)
-                return fixup_out_of_date_error(path, kind, err);
+                return svn_error_return(fixup_out_of_date_error(path, kind,
+                                                                err));
             }
         }
       else
@@ -1502,7 +1504,7 @@ do_item_commit(void **dir_baton,
               (kind == svn_node_dir) ? *dir_baton : file_baton, pool);
 
       if (err)
-        return fixup_out_of_date_error(path, kind, err);
+        return svn_error_return(fixup_out_of_date_error(path, kind, err));
 
       SVN_ERR(svn_wc_transmit_prop_deltas2(
                 ctx->wc_ctx, local_abspath, editor,
@@ -1548,7 +1550,8 @@ do_item_commit(void **dir_baton,
                                     file_pool, &file_baton);
 
           if (err)
-            return fixup_out_of_date_error(path, item->kind, err);
+            return svn_error_return(fixup_out_of_date_error(path, item->kind,
+                                                            err));
         }
 
       /* Add this file mod to the FILE_MODS hash. */

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_client/merge.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_client/merge.c Thu Apr  8 15:52:53 2010
@@ -8270,22 +8270,21 @@ merge_cousins_and_supplement_mergeinfo(c
 
 /*** Public APIs ***/
 
-svn_error_t *
-svn_client_merge3(const char *source1,
-                  const svn_opt_revision_t *revision1,
-                  const char *source2,
-                  const svn_opt_revision_t *revision2,
-                  const char *target_wcpath,
-                  svn_depth_t depth,
-                  svn_boolean_t ignore_ancestry,
-                  svn_boolean_t force,
-                  svn_boolean_t record_only,
-                  svn_boolean_t dry_run,
-                  const apr_array_header_t *merge_options,
-                  svn_client_ctx_t *ctx,
-                  apr_pool_t *pool)
+static svn_error_t *
+merge_locked(const char *source1,
+             const svn_opt_revision_t *revision1,
+             const char *source2,
+             const svn_opt_revision_t *revision2,
+             const char *target_abspath,
+             svn_depth_t depth,
+             svn_boolean_t ignore_ancestry,
+             svn_boolean_t force,
+             svn_boolean_t record_only,
+             svn_boolean_t dry_run,
+             const apr_array_header_t *merge_options,
+             svn_client_ctx_t *ctx,
+             apr_pool_t *scratch_pool)
 {
-  svn_wc_adm_access_t *adm_access;
   const char *URL1, *URL2;
   svn_revnum_t rev1, rev2;
   svn_boolean_t related = FALSE, ancestral = FALSE;
@@ -8302,9 +8301,6 @@ svn_client_merge3(const char *source1,
   apr_pool_t *sesspool;
   svn_boolean_t same_repos;
   const char *source_repos_uuid1, *source_repos_uuid2;
-  const char *target_abspath;
-
-  SVN_ERR(svn_dirent_get_absolute(&target_abspath, target_wcpath, pool));
 
   /* Sanity check our input -- we require specified revisions. */
   if ((revision1->kind == svn_opt_revision_unspecified)
@@ -8324,31 +8320,28 @@ svn_client_merge3(const char *source1,
      able to figure out some kind of revision specifications, but in
      that case it won't matter, because those ways of specifying a
      revision are meaningless for a url. */
-  SVN_ERR(svn_client_url_from_path2(&URL1, source1, ctx, pool, pool));
+  SVN_ERR(svn_client_url_from_path2(&URL1, source1, ctx,
+                                    scratch_pool, scratch_pool));
   if (! URL1)
     return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
                              _("'%s' has no URL"),
-                             svn_dirent_local_style(source1, pool));
+                             svn_dirent_local_style(source1, scratch_pool));
 
-  SVN_ERR(svn_client_url_from_path2(&URL2, source2, ctx, pool, pool));
+  SVN_ERR(svn_client_url_from_path2(&URL2, source2, ctx,
+                                    scratch_pool, scratch_pool));
   if (! URL2)
     return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
                              _("'%s' has no URL"),
-                             svn_dirent_local_style(source2, pool));
-
-  /* Open an admistrative session with the working copy. */
-  SVN_ERR(svn_wc__adm_probe_in_context(&adm_access, ctx->wc_ctx,
-                                       target_abspath,
-                                       !dry_run, -1, ctx->cancel_func,
-                                       ctx->cancel_baton, pool));
+                             svn_dirent_local_style(source2, scratch_pool));
 
   /* Determine the working copy target's repository root URL. */
   working_rev.kind = svn_opt_revision_working;
   SVN_ERR(svn_client__get_repos_root(&wc_repos_root, target_abspath,
-                                     &working_rev, ctx, pool, pool));
+                                     &working_rev, ctx,
+                                     scratch_pool, scratch_pool));
 
   /* Open some RA sessions to our merge source sides. */
-  sesspool = svn_pool_create(pool);
+  sesspool = svn_pool_create(scratch_pool);
   SVN_ERR(svn_client__open_ra_session_internal(&ra_session1,
                                                URL1, NULL, NULL,
                                                FALSE, TRUE, ctx, sesspool));
@@ -8364,8 +8357,8 @@ svn_client_merge3(const char *source1,
                                           NULL, ra_session2, revision2,
                                           sesspool));
 
-  SVN_ERR(svn_ra_get_uuid2(ra_session1, &source_repos_uuid1, pool));
-  SVN_ERR(svn_ra_get_uuid2(ra_session2, &source_repos_uuid2, pool));
+  SVN_ERR(svn_ra_get_uuid2(ra_session1, &source_repos_uuid1, scratch_pool));
+  SVN_ERR(svn_ra_get_uuid2(ra_session2, &source_repos_uuid2, scratch_pool));
 
   /* We can't do a diff between different repositories. */
   if (strcmp(source_repos_uuid1, source_repos_uuid2) != 0)
@@ -8382,7 +8375,7 @@ svn_client_merge3(const char *source1,
       const char *wc_repos_uuid;
 
       SVN_ERR(svn_client_uuid_from_path2(&wc_repos_uuid, target_abspath,
-                                         ctx, pool, pool));
+                                         ctx, scratch_pool, scratch_pool));
       same_repos = (strcmp(wc_repos_uuid, source_repos_uuid1) == 0);
     }
   else
@@ -8393,7 +8386,7 @@ svn_client_merge3(const char *source1,
     SVN_ERR(svn_client__get_youngest_common_ancestor(&yc_path, &yc_rev,
                                                      URL1, rev1,
                                                      URL2, rev2,
-                                                     ctx, pool));
+                                                     ctx, scratch_pool));
 
   /* Check for a youngest common ancestor.  If we have one, we'll be
      doing merge tracking.
@@ -8423,41 +8416,46 @@ svn_client_merge3(const char *source1,
       related = TRUE;
 
       /* Make YC_PATH into a full URL. */
-      yc_path = svn_path_url_add_component2(source_repos_root, yc_path, pool);
+      yc_path = svn_path_url_add_component2(source_repos_root, yc_path,
+                                            scratch_pool);
 
       /* If the common ancestor matches the right side of our merge,
          then we only need to reverse-merge the left side. */
       if ((strcmp(yc_path, URL2) == 0) && (yc_rev == rev2))
         {
           ancestral = TRUE;
-          range = apr_pcalloc(pool, sizeof(*range));
+          range = apr_pcalloc(scratch_pool, sizeof(*range));
           range->start.kind = svn_opt_revision_number;
           range->start.value.number = rev1;
           range->end.kind = svn_opt_revision_number;
           range->end.value.number = yc_rev;
-          ranges = apr_array_make(pool, 2, sizeof(svn_opt_revision_range_t *));
+          ranges = apr_array_make(scratch_pool,
+                                  2, sizeof(svn_opt_revision_range_t *));
           APR_ARRAY_PUSH(ranges, svn_opt_revision_range_t *) = range;
           peg_revision.value.number = rev1;
           SVN_ERR(normalize_merge_sources(&merge_sources, URL1, URL1,
                                           source_repos_root, &peg_revision,
-                                          ranges, ra_session1, ctx, pool));
+                                          ranges, ra_session1, ctx,
+                                          scratch_pool));
         }
       /* If the common ancestor matches the left side of our merge,
          then we only need to merge the right side. */
       else if ((strcmp(yc_path, URL1) == 0) && (yc_rev == rev1))
         {
           ancestral = TRUE;
-          range = apr_pcalloc(pool, sizeof(*range));
+          range = apr_pcalloc(scratch_pool, sizeof(*range));
           range->start.kind = svn_opt_revision_number;
           range->start.value.number = yc_rev;
           range->end.kind = svn_opt_revision_number;
           range->end.value.number = rev2;
-          ranges = apr_array_make(pool, 2, sizeof(svn_opt_revision_range_t *));
+          ranges = apr_array_make(scratch_pool,
+                                  2, sizeof(svn_opt_revision_range_t *));
           APR_ARRAY_PUSH(ranges, svn_opt_revision_range_t *) = range;
           peg_revision.value.number = rev2;
           SVN_ERR(normalize_merge_sources(&merge_sources, URL2, URL2,
                                           source_repos_root, &peg_revision,
-                                          ranges, ra_session2, ctx, pool));
+                                          ranges, ra_session2, ctx,
+                                          scratch_pool));
         }
       /* And otherwise, we need to do both: reverse merge the left
          side, and merge the right. */
@@ -8475,11 +8473,11 @@ svn_client_merge3(const char *source1,
                                                        record_only, dry_run,
                                                        merge_options,
                                                        &use_sleep, ctx,
-                                                       pool);
+                                                       scratch_pool);
           if (err)
             {
               if (use_sleep)
-                svn_io_sleep_for_timestamps(target_wcpath, pool);
+                svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
 
               return svn_error_return(err);
             }
@@ -8489,14 +8487,14 @@ svn_client_merge3(const char *source1,
              the merge_cousins_and_supplement_mergeinfo() routine). */
           svn_pool_destroy(sesspool);
 
-          return svn_wc_adm_close2(adm_access, pool);
+          return SVN_NO_ERROR;
         }
     }
   else
     {
       /* Build a single-item merge_source_t array. */
-      merge_sources = apr_array_make(pool, 1, sizeof(merge_source_t *));
-      merge_source = apr_pcalloc(pool, sizeof(*merge_source));
+      merge_sources = apr_array_make(scratch_pool, 1, sizeof(merge_source_t *));
+      merge_source = apr_pcalloc(scratch_pool, sizeof(*merge_source));
       merge_source->url1 = URL1;
       merge_source->url2 = URL2;
       merge_source->rev1 = rev1;
@@ -8511,15 +8509,105 @@ svn_client_merge3(const char *source1,
                  ancestral, related, same_repos,
                  ignore_ancestry, force, dry_run,
                  record_only, NULL, FALSE, FALSE, depth, merge_options,
-                 &use_sleep, ctx, pool);
+                 &use_sleep, ctx, scratch_pool);
 
   if (use_sleep)
-    svn_io_sleep_for_timestamps(target_wcpath, pool);
+    svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
 
   if (err)
     return svn_error_return(err);
 
-  return svn_wc_adm_close2(adm_access, pool);
+  return SVN_NO_ERROR;
+}
+
+struct merge_baton {
+  const char *source1;
+  const svn_opt_revision_t *revision1;
+  const char *source2;
+  const svn_opt_revision_t *revision2;
+  const char *target_abspath;
+  svn_depth_t depth;
+  svn_boolean_t ignore_ancestry;
+  svn_boolean_t force;
+  svn_boolean_t record_only;
+  svn_boolean_t dry_run;
+  const apr_array_header_t *merge_options;
+  svn_client_ctx_t *ctx;
+};
+
+/* Implements svn_wc__with_write_lock_func_t. */
+static svn_error_t *
+merge_cb(void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+  struct merge_baton *b = baton;
+
+  SVN_ERR(merge_locked(b->source1, b->revision1, b->source2, b->revision2,
+                       b->target_abspath, b->depth, b->ignore_ancestry,
+                       b->force, b->record_only, b->dry_run,
+                       b->merge_options, b->ctx, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Set *TARGET_ABSPATH to the absolute path of, and *LOCK_ABSPATH to
+ the absolute path to lock for, TARGET_WCPATH. */
+static svn_error_t *
+get_target_and_lock_abspath(const char **target_abspath,
+                            const char **lock_abspath,
+                            const char *target_wcpath,
+                            svn_client_ctx_t *ctx,
+                            apr_pool_t *scratch_pool)
+{
+  svn_node_kind_t kind;
+  SVN_ERR(svn_dirent_get_absolute(target_abspath, target_wcpath, scratch_pool));
+  SVN_ERR(svn_wc__node_get_kind(&kind, ctx->wc_ctx, *target_abspath, FALSE,
+                                scratch_pool));
+  if (kind == svn_node_dir)
+    *lock_abspath = *target_abspath;
+  else
+    *lock_abspath = svn_dirent_dirname(*target_abspath, scratch_pool);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_merge3(const char *source1,
+                  const svn_opt_revision_t *revision1,
+                  const char *source2,
+                  const svn_opt_revision_t *revision2,
+                  const char *target_wcpath,
+                  svn_depth_t depth,
+                  svn_boolean_t ignore_ancestry,
+                  svn_boolean_t force,
+                  svn_boolean_t record_only,
+                  svn_boolean_t dry_run,
+                  const apr_array_header_t *merge_options,
+                  svn_client_ctx_t *ctx,
+                  apr_pool_t *pool)
+{
+  const char *target_abspath, *lock_abspath;
+  struct merge_baton baton;
+
+  SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
+                                      target_wcpath, ctx, pool));
+
+  baton.source1 = source1;
+  baton.revision1 = revision1;
+  baton.source2 = source2;
+  baton.revision2 = revision2;
+  baton.target_abspath = target_abspath;
+  baton.depth = depth;
+  baton.ignore_ancestry = ignore_ancestry;
+  baton.force = force;
+  baton.record_only = record_only;
+  baton.dry_run = dry_run;
+  baton.merge_options = merge_options;
+  baton.ctx = ctx;
+
+  SVN_ERR(svn_wc__call_with_write_lock(merge_cb, &baton, ctx->wc_ctx,
+                                       lock_abspath, pool, pool));
+
+  return SVN_NO_ERROR;
 }
 
 
@@ -9428,16 +9516,15 @@ get_subtree_mergeinfo_walk_cb(const char
   return SVN_NO_ERROR;
 }
 
-svn_error_t *
-svn_client_merge_reintegrate(const char *source,
-                             const svn_opt_revision_t *peg_revision,
-                             const char *target_wcpath,
-                             svn_boolean_t dry_run,
-                             const apr_array_header_t *merge_options,
-                             svn_client_ctx_t *ctx,
-                             apr_pool_t *pool)
+static svn_error_t *
+merge_reintegrate_locked(const char *source,
+                         const svn_opt_revision_t *peg_revision,
+                         const char *target_abspath,
+                         svn_boolean_t dry_run,
+                         const apr_array_header_t *merge_options,
+                         svn_client_ctx_t *ctx,
+                         apr_pool_t *scratch_pool)
 {
-  svn_wc_adm_access_t *adm_access;
   const char *wc_repos_root, *source_repos_root;
   svn_opt_revision_t working_revision;
   svn_ra_session_t *ra_session;
@@ -9452,47 +9539,44 @@ svn_client_merge_reintegrate(const char 
   svn_boolean_t use_sleep = FALSE;
   svn_error_t *err;
   struct get_subtree_mergeinfo_walk_baton wb;
-  const char *target_abspath;
   const char *target_url;
   svn_revnum_t target_base_rev;
 
-  SVN_ERR(svn_dirent_get_absolute(&target_abspath, target_wcpath, pool));
-
-  /* Open an admistrative session with the working copy. */
-  SVN_ERR(svn_wc__adm_probe_in_context(&adm_access, ctx->wc_ctx,
-                                       target_abspath,
-                                       (! dry_run), -1, ctx->cancel_func,
-                                       ctx->cancel_baton, pool));
-
   /* Make sure we're dealing with a real URL. */
-  SVN_ERR(svn_client_url_from_path2(&url2, source, ctx, pool, pool));
+  SVN_ERR(svn_client_url_from_path2(&url2, source, ctx,
+                                    scratch_pool, scratch_pool));
   if (! url2)
     return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
                              _("'%s' has no URL"),
-                             svn_dirent_local_style(source, pool));
+                             svn_dirent_local_style(source, scratch_pool));
 
   /* Determine the working copy target's repository root URL. */
   working_revision.kind = svn_opt_revision_working;
   SVN_ERR(svn_client__get_repos_root(&wc_repos_root, target_abspath,
-                                     &working_revision, ctx, pool, pool));
+                                     &working_revision, ctx,
+                                     scratch_pool, scratch_pool));
 
   /* Open an RA session to our source URL, and determine its root URL. */
   SVN_ERR(svn_client__open_ra_session_internal(&ra_session, wc_repos_root,
                                                NULL, NULL,
-                                               FALSE, FALSE, ctx, pool));
-  SVN_ERR(svn_ra_get_repos_root2(ra_session, &source_repos_root, pool));
+                                               FALSE, FALSE, ctx,
+                                               scratch_pool));
+  SVN_ERR(svn_ra_get_repos_root2(ra_session, &source_repos_root, scratch_pool));
 
   /* source_repos_root and wc_repos_root are required to be the same,
      as mergeinfo doesn't come into play for cross-repository merging. */
   if (strcmp(source_repos_root, wc_repos_root) != 0)
     return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
                              _("'%s' must be from the same repository as "
-                               "'%s'"), svn_dirent_local_style(source, pool),
-                             svn_dirent_local_style(target_wcpath, pool));
+                               "'%s'"), svn_dirent_local_style(source,
+                                                               scratch_pool),
+                             svn_dirent_local_style(target_abspath,
+                                                    scratch_pool));
 
-  SVN_ERR(ensure_wc_reflects_repository_subtree(target_abspath, ctx, pool));
+  SVN_ERR(ensure_wc_reflects_repository_subtree(target_abspath, ctx,
+                                                scratch_pool));
   SVN_ERR(svn_wc__node_get_base_rev(&target_base_rev, ctx->wc_ctx,
-                                    target_abspath, pool));
+                                    target_abspath, scratch_pool));
 
   /* As the WC tree is "pure", use its last-updated-to revision as
      the default revision for the left side of our merge, since that's
@@ -9502,11 +9586,12 @@ svn_client_merge_reintegrate(const char 
 
   SVN_ERR(svn_client__path_relative_to_root(&source_repos_rel_path,
                                             ctx->wc_ctx, url2, NULL, FALSE,
-                                            ra_session, pool, pool));
+                                            ra_session,
+                                            scratch_pool, scratch_pool));
   SVN_ERR(svn_client__path_relative_to_root(&target_repos_rel_path,
                                             ctx->wc_ctx, target_abspath,
                                             wc_repos_root, FALSE, ra_session,
-                                            pool, pool));
+                                            scratch_pool, scratch_pool));
 
   /* Can't reintegrate to or from the root of the repository. */
   if (svn_path_is_empty(source_repos_rel_path)
@@ -9518,17 +9603,18 @@ svn_client_merge_reintegrate(const char 
   /* Find all the subtree's in TARGET_WCPATH that have explicit mergeinfo. */
   wb.target_abspath = target_abspath;
   wb.target_repos_root = wc_repos_root;
-  wb.subtrees_with_mergeinfo = apr_hash_make(pool);
+  wb.subtrees_with_mergeinfo = apr_hash_make(scratch_pool);
   wb.ctx = ctx;
   SVN_ERR(svn_wc__node_walk_children(ctx->wc_ctx, target_abspath, TRUE,
                                      get_subtree_mergeinfo_walk_cb, &wb,
                                      svn_depth_infinity,
                                      ctx->cancel_func, ctx->cancel_baton,
-                                     pool));
+                                     scratch_pool));
 
   SVN_ERR(svn_client__get_revision_number(&rev2, NULL, ctx->wc_ctx,
                                           source_repos_rel_path,
-                                          ra_session, peg_revision, pool));
+                                          ra_session, peg_revision,
+                                          scratch_pool));
 
   SVN_ERR(calculate_left_hand_side(&url1, &rev1,
                                    &merged_to_source_mergeinfo_catalog,
@@ -9541,13 +9627,13 @@ svn_client_merge_reintegrate(const char 
                                    rev2,
                                    ra_session,
                                    ctx,
-                                   pool));
+                                   scratch_pool));
 
   SVN_ERR(svn_client__get_youngest_common_ancestor(&yc_ancestor_path,
                                                    &yc_ancestor_rev,
                                                    url2, rev2,
                                                    url1, rev1,
-                                                   ctx, pool));
+                                                   ctx, scratch_pool));
 
   if (!(yc_ancestor_path && SVN_IS_VALID_REVNUM(yc_ancestor_rev)))
     return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
@@ -9559,14 +9645,14 @@ svn_client_merge_reintegrate(const char 
       /* Have we actually merged anything to the source from the
          target?  If so, make sure we've merged a contiguous
          prefix. */
-      final_unmerged_catalog = apr_hash_make(pool);
+      final_unmerged_catalog = apr_hash_make(scratch_pool);
 
       SVN_ERR(find_unsynced_ranges(source_repos_rel_path,
                                    yc_ancestor_path,
                                    unmerged_to_source_mergeinfo_catalog,
                                    merged_to_source_mergeinfo_catalog,
                                    final_unmerged_catalog,
-                                   ra_session, pool, pool));
+                                   ra_session, scratch_pool, scratch_pool));
 
       if (apr_hash_count(final_unmerged_catalog))
         {
@@ -9575,9 +9661,10 @@ svn_client_merge_reintegrate(const char 
           SVN_ERR(svn_mergeinfo__catalog_to_formatted_string(
             &source_mergeinfo_cat_string,
             final_unmerged_catalog,
-            "  ", "    Missing ranges: ", pool));
+            "  ", "    Missing ranges: ", scratch_pool));
           SVN_ERR(svn_wc__node_get_url(&target_url, ctx->wc_ctx,
-                                       target_abspath, pool, pool));
+                                       target_abspath,
+                                       scratch_pool, scratch_pool));
           return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE,
                                    NULL,
                                    _("Reintegrate can only be used if "
@@ -9608,35 +9695,84 @@ svn_client_merge_reintegrate(const char 
                                                svn_depth_infinity,
                                                FALSE, FALSE, FALSE, dry_run,
                                                merge_options, &use_sleep,
-                                               ctx, pool);
+                                               ctx, scratch_pool);
 
   if (use_sleep)
-    svn_io_sleep_for_timestamps(target_wcpath, pool);
+    svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
 
   if (err)
     return svn_error_return(err);
 
-  /* Shutdown the administrative session. */
-  return svn_wc_adm_close2(adm_access, pool);
+  return SVN_NO_ERROR;
 }
 
+struct merge_reintegrate_baton {
+  const char *source;
+  const svn_opt_revision_t *peg_revision;
+  const char *target_abspath;
+  svn_boolean_t dry_run;
+  const apr_array_header_t *merge_options;
+  svn_client_ctx_t *ctx;
+};
 
+/* Implements svn_wc__with_write_lock_func_t. */
+static svn_error_t *
+merge_reintegrate_cb(void *baton,
+                     apr_pool_t *result_pool,
+                     apr_pool_t *scratch_pool)
+{
+  struct merge_reintegrate_baton *b = baton;
+
+  SVN_ERR(merge_reintegrate_locked(b->source, b->peg_revision,
+                                   b->target_abspath, b->dry_run,
+                                   b->merge_options, b->ctx,
+                                   scratch_pool));
+
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
-svn_client_merge_peg3(const char *source,
-                      const apr_array_header_t *ranges_to_merge,
-                      const svn_opt_revision_t *peg_revision,
-                      const char *target_wcpath,
-                      svn_depth_t depth,
-                      svn_boolean_t ignore_ancestry,
-                      svn_boolean_t force,
-                      svn_boolean_t record_only,
-                      svn_boolean_t dry_run,
-                      const apr_array_header_t *merge_options,
-                      svn_client_ctx_t *ctx,
-                      apr_pool_t *pool)
+svn_client_merge_reintegrate(const char *source,
+                             const svn_opt_revision_t *peg_revision,
+                             const char *target_wcpath,
+                             svn_boolean_t dry_run,
+                             const apr_array_header_t *merge_options,
+                             svn_client_ctx_t *ctx,
+                             apr_pool_t *pool)
+{
+  const char *target_abspath, *lock_abspath;
+  struct merge_reintegrate_baton baton;
+
+  SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
+                                      target_wcpath, ctx, pool));
+
+  baton.source = source;
+  baton.peg_revision = peg_revision;
+  baton.target_abspath = target_abspath;
+  baton.dry_run = dry_run;
+  baton.merge_options = merge_options;
+  baton.ctx = ctx;
+
+  SVN_ERR(svn_wc__call_with_write_lock(merge_reintegrate_cb, &baton,
+                                       ctx->wc_ctx, lock_abspath, pool, pool));
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+merge_peg_locked(const char *source,
+                 const apr_array_header_t *ranges_to_merge,
+                 const svn_opt_revision_t *peg_revision,
+                 const char *target_abspath,
+                 svn_depth_t depth,
+                 svn_boolean_t ignore_ancestry,
+                 svn_boolean_t force,
+                 svn_boolean_t record_only,
+                 svn_boolean_t dry_run,
+                 const apr_array_header_t *merge_options,
+                 svn_client_ctx_t *ctx,
+                 apr_pool_t *scratch_pool)
 {
-  svn_wc_adm_access_t *adm_access;
   const char *URL;
   apr_array_header_t *merge_sources;
   const char *wc_repos_root, *source_repos_root;
@@ -9646,42 +9782,34 @@ svn_client_merge_peg3(const char *source
   svn_boolean_t use_sleep = FALSE;
   svn_error_t *err;
   svn_boolean_t same_repos;
-  const char *target_abspath;
-
-  /* No ranges to merge?  No problem. */
-  if (ranges_to_merge->nelts == 0)
-    return SVN_NO_ERROR;
 
-  SVN_ERR(svn_dirent_get_absolute(&target_abspath, target_wcpath, pool));
-
-  /* Open an admistrative session with the working copy. */
-  SVN_ERR(svn_wc__adm_probe_in_context(&adm_access, ctx->wc_ctx,
-                                       target_abspath,
-                                       (! dry_run), -1, ctx->cancel_func,
-                                       ctx->cancel_baton, pool));
+  SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
 
   /* Make sure we're dealing with a real URL. */
-  SVN_ERR(svn_client_url_from_path2(&URL, source, ctx, pool, pool));
+  SVN_ERR(svn_client_url_from_path2(&URL, source, ctx,
+                                    scratch_pool, scratch_pool));
   if (! URL)
     return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL,
                              _("'%s' has no URL"),
-                             svn_dirent_local_style(source, pool));
+                             svn_dirent_local_style(source, scratch_pool));
 
   /* Determine the working copy target's repository root URL. */
   working_rev.kind = svn_opt_revision_working;
   SVN_ERR(svn_client__get_repos_root(&wc_repos_root, target_abspath,
-                                     &working_rev, ctx, pool, pool));
+                                     &working_rev, ctx,
+                                     scratch_pool, scratch_pool));
 
   /* Open an RA session to our source URL, and determine its root URL. */
-  sesspool = svn_pool_create(pool);
+  sesspool = svn_pool_create(scratch_pool);
   SVN_ERR(svn_client__open_ra_session_internal(&ra_session, URL, NULL, NULL,
                                                FALSE, TRUE, ctx, sesspool));
-  SVN_ERR(svn_ra_get_repos_root2(ra_session, &source_repos_root, pool));
+  SVN_ERR(svn_ra_get_repos_root2(ra_session, &source_repos_root, scratch_pool));
 
   /* Normalize our merge sources. */
   SVN_ERR(normalize_merge_sources(&merge_sources, source, URL,
                                   source_repos_root, peg_revision,
-                                  ranges_to_merge, ra_session, ctx, pool));
+                                  ranges_to_merge, ra_session, ctx,
+                                  scratch_pool));
 
   /* Check for same_repos. */
   if (strcmp(wc_repos_root, source_repos_root) != 0)
@@ -9689,9 +9817,9 @@ svn_client_merge_peg3(const char *source
       const char *source_repos_uuid;
       const char *wc_repos_uuid;
 
-      SVN_ERR(svn_ra_get_uuid2(ra_session, &source_repos_uuid, pool));
+      SVN_ERR(svn_ra_get_uuid2(ra_session, &source_repos_uuid, scratch_pool));
       SVN_ERR(svn_client_uuid_from_path2(&wc_repos_uuid, target_abspath,
-                                         ctx, pool, pool));
+                                         ctx, scratch_pool, scratch_pool));
       same_repos = (strcmp(wc_repos_uuid, source_repos_uuid) == 0);
     }
   else
@@ -9705,14 +9833,83 @@ svn_client_merge_peg3(const char *source
   err = do_merge(NULL, merge_sources, target_abspath,
                  TRUE, TRUE, same_repos, ignore_ancestry, force, dry_run,
                  record_only, NULL, FALSE, FALSE, depth, merge_options,
-                 &use_sleep, ctx, pool);
+                 &use_sleep, ctx, scratch_pool);
 
   if (use_sleep)
-    svn_io_sleep_for_timestamps(target_wcpath, pool);
+    svn_io_sleep_for_timestamps(target_abspath, scratch_pool);
 
   if (err)
     return svn_error_return(err);
 
-  /* Shutdown the administrative session. */
-  return svn_wc_adm_close2(adm_access, pool);
+  return SVN_NO_ERROR;
+}
+
+struct merge_peg_baton {
+  const char *source;
+  const apr_array_header_t *ranges_to_merge;
+  const svn_opt_revision_t *peg_revision;
+  const char *target_abspath;
+  svn_depth_t depth;
+  svn_boolean_t ignore_ancestry;
+  svn_boolean_t force;
+  svn_boolean_t record_only;
+  svn_boolean_t dry_run;
+  const apr_array_header_t *merge_options;
+  svn_client_ctx_t *ctx;
+};
+
+/* Implements svn_wc__with_write_lock_func_t. */
+static svn_error_t *
+merge_peg_cb(void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+  struct merge_peg_baton *b = baton;
+
+  SVN_ERR(merge_peg_locked(b->source, b->ranges_to_merge, b->peg_revision,
+                           b->target_abspath, b->depth, b->ignore_ancestry,
+                           b->force, b->record_only, b->dry_run,
+                           b->merge_options, b->ctx, scratch_pool));
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_merge_peg3(const char *source,
+                      const apr_array_header_t *ranges_to_merge,
+                      const svn_opt_revision_t *peg_revision,
+                      const char *target_wcpath,
+                      svn_depth_t depth,
+                      svn_boolean_t ignore_ancestry,
+                      svn_boolean_t force,
+                      svn_boolean_t record_only,
+                      svn_boolean_t dry_run,
+                      const apr_array_header_t *merge_options,
+                      svn_client_ctx_t *ctx,
+                      apr_pool_t *pool)
+{
+  const char *target_abspath, *lock_abspath;
+  struct merge_peg_baton baton;
+
+  /* No ranges to merge?  No problem. */
+  if (ranges_to_merge->nelts == 0)
+    return SVN_NO_ERROR;
+
+  SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
+                                      target_wcpath, ctx, pool));
+
+  baton.source = source;
+  baton.ranges_to_merge = ranges_to_merge;
+  baton.peg_revision = peg_revision;
+  baton.target_abspath = target_abspath;
+  baton.depth = depth;
+  baton.ignore_ancestry = ignore_ancestry;
+  baton.force = force;
+  baton.record_only = record_only;
+  baton.dry_run = dry_run;
+  baton.merge_options = merge_options;
+  baton.ctx = ctx;
+
+  SVN_ERR(svn_wc__call_with_write_lock(merge_peg_cb, &baton, ctx->wc_ctx,
+                                       lock_abspath, pool, pool));
+
+  return SVN_NO_ERROR;
 }

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_client/mergeinfo.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_client/mergeinfo.c Thu Apr  8 15:52:53 2010
@@ -947,12 +947,11 @@ svn_client__elide_mergeinfo(const char *
 }
 
 
-/* If the server does not support Merge Tracking then return an error with
-   the code SVN_ERR_UNSUPPORTED_FEATURE.  Otherwise, if INCLUDE_DESCENDANTS
-   is false then get the explicit or inherited mergeinfo for PATH_OR_URL
-   @PEG_REVISION and put it in *TARGET_MERGEINFO, keyed to the repository
-   root-relative path of PATH_OR_URL.  If INCLUDE_DESCENDANTS is true then
-   also get the explicit mergeinfo on any subtrees under PATH_OR_URL.
+/* Set *MERGEINFO_CATALOG to the explicit or inherited mergeinfo for
+   PATH_OR_URL@PEG_REVISION.  If INCLUDE_DESCENDANTS is true, also
+   store in *MERGEINFO_CATALOG the explicit mergeinfo on any subtrees
+   under PATH_OR_URL.  Key all mergeinfo in *MERGEINFO_CATALOG on
+   repository relpaths.
 
    If no mergeinfo is found then set *MERGEINFO_CATALOG to NULL.
 
@@ -960,7 +959,10 @@ svn_client__elide_mergeinfo(const char *
    PATH_OR_URL.
 
    Allocate *MERGEINFO_CATALOG and all its contents in RESULT_POOL.  Use
-   SCRATCH_POOL for all temporary allocations.  */
+   SCRATCH_POOL for all temporary allocations.
+
+   Return SVN_ERR_UNSUPPORTED_FEATURE if the server does not support
+   Merge Tracking.  */
 static svn_error_t *
 get_mergeinfo(svn_mergeinfo_catalog_t *mergeinfo_catalog,
               const char **repos_root,
@@ -1029,8 +1031,7 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
 
   if (is_url)
     {
-      const char *repos_rel_path;
-      const char *old_session_url;
+      svn_mergeinfo_catalog_t tmp_catalog;
 
       SVN_ERR(svn_dirent_get_absolute(&local_abspath, "", scratch_pool));
       SVN_ERR(svn_client__open_ra_session_internal(&ra_session, path_or_url,
@@ -1040,21 +1041,43 @@ get_mergeinfo(svn_mergeinfo_catalog_t *m
                                               local_abspath, ra_session,
                                               &peg_rev, scratch_pool));
       SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, scratch_pool));
-      SVN_ERR(svn_client__path_relative_to_root(&repos_rel_path, ctx->wc_ctx,
-                                                path_or_url, *repos_root,
-                                                FALSE, NULL,
-                                                scratch_pool,
-                                                scratch_pool));
-      SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
-                                                *repos_root, scratch_pool));
-      SVN_ERR(svn_client__get_repos_mergeinfo_catalog(mergeinfo_catalog,
+      SVN_ERR(svn_client__get_repos_mergeinfo_catalog(&tmp_catalog,
                                                       ra_session,
-                                                      repos_rel_path, rev,
+                                                      "", rev,
                                                       svn_mergeinfo_inherited,
                                                       FALSE,
                                                       include_descendants,
                                                       result_pool,
                                                       scratch_pool));
+
+      /* If we're not querying the root of the repository, the catalog
+         we fetched will be keyed on paths relative to the session
+         URL.  But our caller is expecting repository relpaths.  So we
+         do a little dance...  */
+      if (tmp_catalog && (strcmp(path_or_url, *repos_root) != 0))
+        {
+          apr_hash_index_t *hi;
+
+          *mergeinfo_catalog = apr_hash_make(result_pool);
+
+          for (hi = apr_hash_first(scratch_pool, tmp_catalog);
+               hi; hi = apr_hash_next(hi))
+            {
+              /* session-relpath -> repos-url -> repos-relpath */
+              const char *path =
+                svn_path_url_add_component2(path_or_url,
+                                            svn__apr_hash_index_key(hi),
+                                            scratch_pool);
+              SVN_ERR(svn_ra_get_path_relative_to_root(ra_session, &path, path,
+                                                       result_pool));
+              apr_hash_set(*mergeinfo_catalog, path, APR_HASH_KEY_STRING,
+                           svn__apr_hash_index_val(hi));
+            }
+        }
+      else
+        {
+          *mergeinfo_catalog = tmp_catalog;
+        }
     }
   else /* ! svn_path_is_url() */
     {

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_diff/parse-diff.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_diff/parse-diff.c Thu Apr  8 15:52:53 2010
@@ -371,8 +371,8 @@ parse_next_hunk(svn_hunk_t **hunk,
               hunk_seen = TRUE;
               changed_line_seen = TRUE;
 
-              /* A hunk may have context in the middle. We only want the
-                 last lines of context. */
+              /* A hunk may have context in the middle. We only want
+                 trailing lines of context. */
               if (trailing_context > 0)
                 trailing_context = 0;
 
@@ -383,8 +383,8 @@ parse_next_hunk(svn_hunk_t **hunk,
               hunk_seen = TRUE;
               changed_line_seen = TRUE;
 
-              /* A hunk may have context in the middle. We only want the
-                 last lines of context. */
+              /* A hunk may have context in the middle. We only want
+                 trailing lines of context. */
               if (trailing_context > 0)
                 trailing_context = 0;
 

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_fs_base/fs.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_fs_base/fs.c Thu Apr  8 15:52:53 2010
@@ -657,20 +657,22 @@ base_create(svn_fs_t *fs, const char *pa
   int format = SVN_FS_BASE__FORMAT_NUMBER;
   svn_error_t *svn_err;
 
-  /* See if we had an explicitly specified pre-1.5-compatible.  */
-  if (fs->config && apr_hash_get(fs->config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE,
-                                 APR_HASH_KEY_STRING))
-    format = 3;
-
-  /* See if we had an explicitly specified pre-1.5-compatible.  */
-  if (fs->config && apr_hash_get(fs->config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE,
-                                 APR_HASH_KEY_STRING))
-    format = 2;
-
-  /* See if we had an explicitly specified pre-1.4-compatible.  */
-  if (fs->config && apr_hash_get(fs->config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE,
-                                 APR_HASH_KEY_STRING))
-    format = 1;
+  /* See if compatibility with older versions was explicitly requested. */
+  if (fs->config)
+    {
+      if (apr_hash_get(fs->config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE,
+                                   APR_HASH_KEY_STRING))
+        format = 1;
+      else if (apr_hash_get(fs->config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE,
+                                        APR_HASH_KEY_STRING))
+        format = 2;
+      else if (apr_hash_get(fs->config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE,
+                                        APR_HASH_KEY_STRING))
+        format = 3;
+      else if (apr_hash_get(fs->config, SVN_FS_CONFIG_PRE_1_7_COMPATIBLE,
+                                        APR_HASH_KEY_STRING))
+        format = 4;
+    }
 
   /* Create the environment and databases. */
   svn_err = open_databases(fs, TRUE, format, path, pool);

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_fs_fs/fs.h?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_fs_fs/fs.h Thu Apr  8 15:52:53 2010
@@ -118,12 +118,12 @@ extern "C" {
 /* The minimum format number that supports packed shards. */
 #define SVN_FS_FS__MIN_PACKED_FORMAT 4
 
-  /* The minimum format number that supports packed revprop shards. */
-#define SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT 5
-
 /* The minimum format number that stores node kinds in changed-paths lists. */
 #define SVN_FS_FS__MIN_KIND_IN_CHANGED_FORMAT 4
 
+/* The minimum format number that supports packed revprop shards. */
+#define SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT 5
+
 /* Private FSFS-specific data shared between all svn_txn_t objects that
    relate to a particular transaction in a filesystem (as identified
    by transaction id and filesystem UUID).  Objects of this type are

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_fs_fs/fs_fs.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_fs_fs/fs_fs.c Thu Apr  8 15:52:53 2010
@@ -6329,7 +6329,7 @@ svn_fs_fs__create(svn_fs_t *fs,
   fs_fs_data_t *ffd = fs->fsap_data;
 
   fs->path = apr_pstrdup(pool, path);
-  /* See if we had an explicitly requested pre-1.4- or pre-1.5-compatible.  */
+  /* See if compatibility with older versions was explicitly requested. */
   if (fs->config)
     {
       if (apr_hash_get(fs->config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE,
@@ -6341,6 +6341,9 @@ svn_fs_fs__create(svn_fs_t *fs,
       else if (apr_hash_get(fs->config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE,
                                         APR_HASH_KEY_STRING))
         format = 3;
+      else if (apr_hash_get(fs->config, SVN_FS_CONFIG_PRE_1_7_COMPATIBLE,
+                                        APR_HASH_KEY_STRING))
+        format = 4;
     }
   ffd->format = format;
 

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_ra_neon/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_ra_neon/mergeinfo.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_ra_neon/mergeinfo.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_ra_neon/mergeinfo.c Thu Apr  8 15:52:53 2010
@@ -116,12 +116,16 @@ end_element(void *baton, int state, cons
       if (mb->curr_info && mb->curr_path)
         {
           svn_mergeinfo_t path_mergeinfo;
+          const char *path;
 
           SVN_ERR_ASSERT(mb->curr_path->data);
+          path = apr_pstrdup(mb->pool, mb->curr_path->data);
           SVN_ERR((mb->err = svn_mergeinfo_parse(&path_mergeinfo,
                                                  mb->curr_info->data,
                                                  mb->pool)));
-          apr_hash_set(mb->catalog, apr_pstrdup(mb->pool, mb->curr_path->data),
+          /* Correct for naughty servers that send "relative" paths
+             with leading slashes! */
+          apr_hash_set(mb->catalog, path[0] == '/' ? path + 1 : path,
                        APR_HASH_KEY_STRING, path_mergeinfo);
         }
     }

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_ra_serf/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_ra_serf/mergeinfo.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_ra_serf/mergeinfo.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_ra_serf/mergeinfo.c Thu Apr  8 15:52:53 2010
@@ -119,14 +119,18 @@ end_element(svn_ra_serf__xml_parser_t *p
       if (mergeinfo_ctx->curr_info && mergeinfo_ctx->curr_path)
         {
           svn_mergeinfo_t path_mergeinfo;
+          const char *path;
 
           SVN_ERR_ASSERT(mergeinfo_ctx->curr_path->data);
+          path = apr_pstrdup(mergeinfo_ctx->pool,
+                             mergeinfo_ctx->curr_path->data);
           SVN_ERR(svn_mergeinfo_parse(&path_mergeinfo,
                                       mergeinfo_ctx->curr_info->data,
                                       mergeinfo_ctx->pool));
+          /* Correct for naughty servers that send "relative" paths
+             with leading slashes! */
           apr_hash_set(mergeinfo_ctx->result_catalog,
-                       apr_pstrdup(mergeinfo_ctx->pool,
-                                   mergeinfo_ctx->curr_path->data),
+                       path[0] == '/' ? path + 1 : path,
                        APR_HASH_KEY_STRING, path_mergeinfo);
         }
       svn_ra_serf__xml_pop_state(parser);

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_ra_svn/client.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_ra_svn/client.c Thu Apr  8 15:52:53 2010
@@ -1156,7 +1156,10 @@ static svn_error_t *ra_svn_get_mergeinfo
           SVN_ERR(svn_ra_svn_parse_tuple(elt->u.list, pool, "cc",
                                          &path, &to_parse));
           SVN_ERR(svn_mergeinfo_parse(&for_path, to_parse, pool));
-          apr_hash_set(*catalog, path, APR_HASH_KEY_STRING, for_path);
+          /* Correct for naughty servers that send "relative" paths
+             with leading slashes! */
+          apr_hash_set(*catalog, path[0] == '/' ? path + 1 : path,
+                       APR_HASH_KEY_STRING, for_path);
         }
     }
 

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_subr/io.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_subr/io.c Thu Apr  8 15:52:53 2010
@@ -224,6 +224,9 @@ io_check_path(const char *path,
     *kind = svn_node_none;
   else if (APR_STATUS_IS_ENOTDIR(apr_err)
 #ifdef WIN32
+           /* On Windows, APR_STATUS_IS_ENOTDIR includes several kinds of
+            * invalid-pathname error but not this one, so we include it. */
+           /* ### This fix should go into APR. */
            || (APR_TO_OS_ERROR(apr_err) == ERROR_INVALID_NAME)
 #endif
            )

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_subr/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_subr/mergeinfo.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_subr/mergeinfo.c Thu Apr  8 15:52:53 2010
@@ -1679,11 +1679,13 @@ svn_mergeinfo__remove_empty_rangelists(s
 svn_error_t *
 svn_mergeinfo__remove_prefix_from_catalog(svn_mergeinfo_catalog_t *out_catalog,
                                           svn_mergeinfo_catalog_t in_catalog,
-                                          const char *prefix,
+                                          const char *prefix_path,
                                           apr_pool_t *pool)
 {
   apr_hash_index_t *hi;
-  size_t prefix_len = strlen(prefix);
+  size_t prefix_len = strlen(prefix_path);
+
+  SVN_ERR_ASSERT(prefix_path[0] == '/');
 
   *out_catalog = apr_hash_make(pool);
 
@@ -1692,12 +1694,21 @@ svn_mergeinfo__remove_prefix_from_catalo
       const char *original_path = svn__apr_hash_index_key(hi);
       apr_ssize_t klen = svn__apr_hash_index_klen(hi);
       svn_mergeinfo_t value = svn__apr_hash_index_val(hi);
+      apr_ssize_t padding = 0;
 
       SVN_ERR_ASSERT(klen >= prefix_len);
-      SVN_ERR_ASSERT(strncmp(original_path, prefix, prefix_len) == 0);
+      SVN_ERR_ASSERT(svn_uri_is_ancestor(prefix_path, original_path));
+
+      /* If the ORIGINAL_PATH doesn't match the PREFIX_PATH exactly
+         and we're not simply removing a single leading slash (such as
+         when PREFIX_PATH is "/"), we advance our string offset by an
+         extra character (to get past the directory separator that
+         follows the prefix).  */
+      if ((strcmp(original_path, prefix_path) != 0) && (prefix_len != 1))
+        padding = 1;
 
-      apr_hash_set(*out_catalog, original_path + prefix_len,
-                   klen-prefix_len, value);
+      apr_hash_set(*out_catalog, original_path + prefix_len + padding,
+                   klen - prefix_len - padding, value);
     }
 
   return SVN_NO_ERROR;

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_files.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_files.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_files.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_files.c Thu Apr  8 15:52:53 2010
@@ -390,6 +390,8 @@ svn_wc__open_adm_stream(svn_stream_t **s
 svn_error_t *
 svn_wc__open_writable_base(svn_stream_t **stream,
                            const char **temp_base_abspath,
+                           svn_checksum_t **md5_checksum,
+                           svn_checksum_t **sha1_checksum,
                            svn_wc__db_t *db,
                            const char *local_abspath,
                            apr_pool_t *result_pool,
@@ -407,6 +409,13 @@ svn_wc__open_writable_base(svn_stream_t 
                                  temp_dir_abspath,
                                  svn_io_file_del_none,
                                  result_pool, scratch_pool));
+  if (md5_checksum)
+    *stream = svn_stream_checksummed2(*stream, NULL, md5_checksum,
+                                      svn_checksum_md5, FALSE, result_pool);
+  if (sha1_checksum)
+    *stream = svn_stream_checksummed2(*stream, NULL, sha1_checksum,
+                                      svn_checksum_sha1, FALSE, result_pool);
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_files.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_files.h?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_files.h (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_files.h Thu Apr  8 15:52:53 2010
@@ -123,12 +123,20 @@ svn_error_t *svn_wc__open_adm_stream(svn
 /* Open a writable stream to a temporary (normal or revert) text base,
    associated with the versioned file LOCAL_ABSPATH in DB.  Set *STREAM to
    the opened stream and *TEMP_BASE_ABSPATH to the path to the temporary
-   file, both allocated in RESULT_POOL.  The temporary file will have an
-   arbitrary unique name, in contrast to the deterministic name that
-   svn_wc__text_base_path(tmp=TRUE) returns. */
+   file.  The temporary file will have an arbitrary unique name, in contrast
+   to the deterministic name that svn_wc__text_base_path(tmp=TRUE) returns.
+
+   Arrange that, on stream closure, *MD5_CHECKSUM and *SHA1_CHECKSUM will be
+   set to the MD-5 and SHA-1 checksums respectively of that file.
+   MD5_CHECKSUM and/or SHA1_CHECKSUM may be NULL if not wanted.
+
+   Allocate the new stream, path and checksums in RESULT_POOL.
+ */
 svn_error_t *
 svn_wc__open_writable_base(svn_stream_t **stream,
                            const char **temp_base_abspath,
+                           svn_checksum_t **md5_checksum,
+                           svn_checksum_t **sha1_checksum,
                            svn_wc__db_t *db,
                            const char *local_abspath,
                            apr_pool_t *result_pool,

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_ops.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_ops.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_ops.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_wc/adm_ops.c Thu Apr  8 15:52:53 2010
@@ -1553,7 +1553,8 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
          only have file locks inside access batons we have to open a new
          access baton for new directories here. svn_wc_add3() handles this
          case when we don't need the access batons for locking. */
-      /* ### This block can be removed after we fully abandon access batons. */
+      /* ### This block can be removed after we fully abandon access batons
+             and centralise the db. */
       if (! exists)
         {
           svn_wc_adm_access_t *adm_access
@@ -1574,6 +1575,13 @@ svn_wc_add4(svn_wc_context_t *wc_ctx,
                                        cancel_func, cancel_baton,
                                        adm_pool));
             }
+          else
+            {
+              /* Lock on parent needs to be propogated into the child db. */
+              SVN_ERR(svn_wc__db_wclock_set(db, local_abspath, 0, pool));
+              SVN_ERR(svn_wc__db_temp_mark_locked(db, local_abspath, pool));
+            }
+
         }
 
       /* We're making the same mods we made above, but this time we'll

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_wc/entries.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_wc/entries.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_wc/entries.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_wc/entries.c Thu Apr  8 15:52:53 2010
@@ -727,6 +727,8 @@ read_entries_new(apr_hash_t **result_ent
                || status == svn_wc__db_status_obstructed_add)
         {
           svn_wc__db_status_t work_status;
+          const char *op_root_abspath;
+          const char *scanned_original_relpath;
           svn_revnum_t original_revision;
 
           /* For child nodes, pick up the parent's revision.  */
@@ -817,17 +819,19 @@ read_entries_new(apr_hash_t **result_ent
             }
 
           SVN_ERR(svn_wc__db_scan_addition(&work_status,
-                                           NULL,
+                                           &op_root_abspath,
                                            &repos_relpath,
                                            &entry->repos,
                                            &entry->uuid,
-                                           NULL, NULL, NULL, &original_revision,
+                                           &scanned_original_relpath,
+                                           NULL, NULL, /* original_root|uuid */
+                                           &original_revision,
                                            db,
                                            entry_abspath,
                                            result_pool, iterpool));
 
           if (!SVN_IS_VALID_REVNUM(entry->cmt_rev)
-              && original_repos_relpath == NULL)
+              && scanned_original_relpath == NULL)
             {
               /* There is NOT a last-changed revision (last-changed date and
                  author may be unknown, but we can always check the rev).
@@ -850,106 +854,146 @@ read_entries_new(apr_hash_t **result_ent
 
               /* Copied nodes need to mirror their copyfrom_rev, if they
                  don't have a revision of their own already. */
-              if (!SVN_IS_VALID_REVNUM(entry->revision))
+              if (!SVN_IS_VALID_REVNUM(entry->revision)
+                  || entry->revision == 0 /* added */)
                 entry->revision = original_revision;
             }
 
           /* Does this node have copyfrom_* information?  */
-          if (original_repos_relpath != NULL)
+          if (scanned_original_relpath != NULL)
             {
-              const char *parent_abspath;
-              svn_boolean_t set_copyfrom = TRUE;
-              svn_error_t *err;
-              const char *op_root_abspath;
-              const char *parent_repos_relpath;
-              const char *parent_root_url;
+              svn_boolean_t is_copied_child;
+              svn_boolean_t is_mixed_rev = FALSE;
 
               SVN_ERR_ASSERT(work_status == svn_wc__db_status_copied);
 
-              /* When we insert entries into the database, we will construct
-                 additional copyfrom records for mixed-revision copies. The
-                 old entries would simply record the different revision in
-                 the entry->revision field. That is not available within
-                 wc-ng, so additional copies are made (see the logic inside
-                 write_entry()). However, when reading these back *out* of
-                 the database, the additional copies look like new "Added"
-                 nodes rather than a simple mixed-rev working copy.
-
-                 That would be a behavior change if we did not compensate.
-                 If there is copyfrom information for this node, then the
-                 code below looks at the parent to detect if it *also* has
-                 copyfrom information, and if the copyfrom_url would align
-                 properly. If it *does*, then we omit storing copyfrom_url
-                 and copyfrom_rev (ie. inherit the copyfrom info like a
-                 normal child), and update entry->revision with the
-                 copyfrom_rev in order to (re)create the mixed-rev copied
-                 subtree that was originally presented for storage.  */
-
-              /* Get the copyfrom information from our parent.
-
-                 Note that the parent could be added/copied/moved-here. There
-                 is no way for it to be deleted/moved-away and have *this*
-                 node appear as copied.  */
-              parent_abspath = svn_dirent_dirname(entry_abspath, iterpool);
-              err = svn_wc__db_scan_addition(NULL,
-                                             &op_root_abspath,
-                                             NULL, NULL, NULL,
-                                             &parent_repos_relpath,
-                                             &parent_root_url,
-                                             NULL, NULL,
-                                             db,
-                                             parent_abspath,
-                                             iterpool, iterpool);
-              if (err)
+              /* If this node inherits copyfrom information from an
+                 ancestor node, then it must be a copied child.  */
+              is_copied_child = (original_repos_relpath == NULL);
+
+              /* If this node has copyfrom information on it, then it may
+                 be an actual copy-root, or it could be participating in
+                 a mixed-revision copied tree. So if we don't already know
+                 this is a copied child, then we need to look for this
+                 mixed-revision situation.  */
+              if (!is_copied_child)
                 {
-                  if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
-                    return svn_error_return(err);
-                  svn_error_clear(err);
+                  const char *parent_abspath;
+                  svn_error_t *err;
+                  const char *parent_repos_relpath;
+                  const char *parent_root_url;
+
+                  /* When we insert entries into the database, we will
+                     construct additional copyfrom records for mixed-revision
+                     copies. The old entries would simply record the different
+                     revision in the entry->revision field. That is not
+                     available within wc-ng, so additional copies are made
+                     (see the logic inside write_entry()). However, when
+                     reading these back *out* of the database, the additional
+                     copies look like new "Added" nodes rather than a simple
+                     mixed-rev working copy.
+
+                     That would be a behavior change if we did not compensate.
+                     If there is copyfrom information for this node, then the
+                     code below looks at the parent to detect if it *also* has
+                     copyfrom information, and if the copyfrom_url would align
+                     properly. If it *does*, then we omit storing copyfrom_url
+                     and copyfrom_rev (ie. inherit the copyfrom info like a
+                     normal child), and update entry->revision with the
+                     copyfrom_rev in order to (re)create the mixed-rev copied
+                     subtree that was originally presented for storage.  */
+
+                  /* Get the copyfrom information from our parent.
+
+                     Note that the parent could be added/copied/moved-here.
+                     There is no way for it to be deleted/moved-away and
+                     have *this* node appear as copied.  */
+                  parent_abspath = svn_dirent_dirname(entry_abspath, iterpool);
+                  err = svn_wc__db_scan_addition(NULL,
+                                                 &op_root_abspath,
+                                                 NULL, NULL, NULL,
+                                                 &parent_repos_relpath,
+                                                 &parent_root_url,
+                                                 NULL, NULL,
+                                                 db,
+                                                 parent_abspath,
+                                                 iterpool, iterpool);
+                  if (err)
+                    {
+                      if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
+                        return svn_error_return(err);
+                      svn_error_clear(err);
+                    }
+                  else if (parent_root_url != NULL
+                           && strcmp(original_root_url, parent_root_url) == 0)
+                    {
+                      const char *relpath_to_entry = svn_dirent_is_child(
+                        op_root_abspath, entry_abspath, NULL);
+                      const char *entry_repos_relpath = svn_relpath_join(
+                        parent_repos_relpath, relpath_to_entry, iterpool);
+
+                      /* The copyfrom repos roots matched.
+
+                         Now we look to see if the copyfrom path of the parent
+                         would align with our own path. If so, then it means
+                         this copyfrom was spontaneously created and inserted
+                         for mixed-rev purposes and can be eliminated without
+                         changing the semantics of a mixed-rev copied subtree.
+
+                         See notes/api-errata/wc003.txt for some additional
+                         detail, and potential issues.  */
+                      if (strcmp(entry_repos_relpath,
+                                 original_repos_relpath) == 0)
+                        {
+                          is_copied_child = TRUE;
+                          is_mixed_rev = TRUE;
+                        }
+                    }
                 }
-              else if (parent_root_url != NULL
-                       && strcmp(original_root_url, parent_root_url) == 0)
+
+              if (is_copied_child)
                 {
+                  /* We won't be settig the  copyfrom_url, yet need to
+                     clear out the copyfrom_rev. Thus, this node becomes a
+                     child of a copied subtree (rather than its own root).  */
+                  entry->copyfrom_rev = SVN_INVALID_REVNUM;
+
+                  /* Children in a copied subtree are schedule normal
+                     since we don't plan to actually *do* anything with
+                     them. Their operation is implied by ancestors.  */
+                  entry->schedule = svn_wc_schedule_normal;
+
+                  /* And *finally* we turn this entry into the mixed
+                     revision node that it was intended to be. This
+                     node's revision is taken from the copyfrom record
+                     that we spontaneously constructed.  */
+                  if (is_mixed_rev)
+                    entry->revision = original_revision;
+                }
+              else if (original_repos_relpath != NULL)
+                {
+                  entry->copyfrom_url =
+                    svn_path_url_add_component2(original_root_url,
+                                                original_repos_relpath,
+                                                result_pool);
+                }
+              else
+                {
+                  /* NOTE: if original_repos_relpath == NULL, then the
+                     second call to scan_addition() will not have occurred.
+                     Thus, this use of OP_ROOT_ABSPATH still contains the
+                     original value where we fetched a value for
+                     SCANNED_REPOS_RELPATH.  */
                   const char *relpath_to_entry = svn_dirent_is_child(
                     op_root_abspath, entry_abspath, NULL);
                   const char *entry_repos_relpath = svn_relpath_join(
-                    parent_repos_relpath, relpath_to_entry, iterpool);
+                    scanned_original_relpath, relpath_to_entry, iterpool);
 
-                  /* The copyfrom repos roots matched.
-
-                     Now we look to see if the copyfrom path of the parent
-                     would align with our own path. If so, then it means
-                     this copyfrom was spontaneously created and inserted
-                     for mixed-rev purposes and can be eliminated without
-                     changing the semantics of a mixed-rev copied subtree.
-
-                     See notes/api-errata/wc003.txt for some additional
-                     detail, and potential issues.  */
-                  if (strcmp(entry_repos_relpath, original_repos_relpath) == 0)
-                    {
-                      /* Don't set the copyfrom_url and clear out the
-                         copyfrom_rev. Thus, this node becomes a child
-                         of a copied subtree (rather than its own root).  */
-                      set_copyfrom = FALSE;
-                      entry->copyfrom_rev = SVN_INVALID_REVNUM;
-
-                      /* Children in a copied subtree are schedule normal
-                         since we don't plan to actually *do* anything with
-                         them. Their operation is implied by ancestors.  */
-                      entry->schedule = svn_wc_schedule_normal;
-
-                      /* And *finally* we turn this entry into the mixed
-                         revision node that it was intended to be. This
-                         node's revision is taken from the copyfrom record
-                         that we spontaneously constructed.  */
-                      entry->revision = original_revision;
-                    }
+                  entry->copyfrom_url =
+                    svn_path_url_add_component2(original_root_url,
+                                                entry_repos_relpath,
+                                                result_pool);
                 }
-
-              if (set_copyfrom)
-                entry->copyfrom_url =
-                  svn_path_url_add_component2(original_root_url,
-                                              original_repos_relpath,
-                                              result_pool);
             }
         }
       else if (status == svn_wc__db_status_not_present)

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_wc/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_wc/log.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_wc/log.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_wc/log.c Thu Apr  8 15:52:53 2010
@@ -142,6 +142,9 @@ struct log_runner
 #define LOG_START "<wc-log xmlns=\"http://subversion.tigris.org/xmlns\">\n"
 #define LOG_END "</wc-log>\n"
 
+/* For log debugging. Generates output about its operation.  */
+/* #define DEBUG_LOG */
+
 
 
 /*** The XML handlers. ***/
@@ -641,6 +644,10 @@ start_handler(void *userData, const char
       return;
     }
 
+#ifdef DEBUG_LOG
+  SVN_DBG(("start_handler: name='%s'\n", eltname));
+#endif
+
   /* Dispatch. */
   if (strcmp(eltname, SVN_WC__LOG_MODIFY_ENTRY) == 0) {
     err = log_do_modify_entry(loggy, name, atts);

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_wc/log.h
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_wc/log.h?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_wc/log.h (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_wc/log.h Thu Apr  8 15:52:53 2010
@@ -302,11 +302,10 @@ svn_wc__loggy_add_tree_conflict(svn_wc__
                                 apr_pool_t *scratch_pool);
 
 
-/* Extend LOG_ACCUM with log entries to save the current baseprops of PATH
-   as revert props.
+/* Extend LOG_ACCUM with log entries to save the current baseprops of
+   LOCAL_ABSPATH as revert props.
 
-   Makes sure the baseprops are destroyed if DESTROY_BASEPROPS is TRUE,
-   the baseprops are preserved otherwise.
+   Makes sure the baseprops are destroyed.
 */
 svn_error_t *
 svn_wc__loggy_revert_props_create(svn_stringbuf_t **log_accum,

Modified: subversion/branches/svn-patch-improvements/subversion/libsvn_wc/props.c
URL: http://svn.apache.org/viewvc/subversion/branches/svn-patch-improvements/subversion/libsvn_wc/props.c?rev=931980&r1=931979&r2=931980&view=diff
==============================================================================
--- subversion/branches/svn-patch-improvements/subversion/libsvn_wc/props.c (original)
+++ subversion/branches/svn-patch-improvements/subversion/libsvn_wc/props.c Thu Apr  8 15:52:53 2010
@@ -537,7 +537,7 @@ svn_wc__loggy_revert_props_create(svn_st
   SVN_ERR(svn_wc__prop_path(&base_prop_abspath, local_abspath, kind,
                             svn_wc__props_base, pool));
 
-  /* If prop base exist, copy it to revert base. */
+  /* If prop base exist, move it to revert base. */
   SVN_ERR(svn_io_check_path(base_prop_abspath, &on_disk, pool));
   if (on_disk == svn_node_file)
     {