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/11/04 21:48:30 UTC

svn commit: r1031230 [4/21] - in /subversion/branches/py-tests-as-modules: ./ build/ build/ac-macros/ build/win32/ contrib/client-side/ notes/ notes/http-and-webdav/ notes/wc-ng/ subversion/bindings/ctypes-python/csvn/ subversion/bindings/javahl/native...

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_client/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_client/deprecated.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_client/deprecated.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_client/deprecated.c Thu Nov  4 20:48:21 2010
@@ -620,7 +620,7 @@ svn_client_move5(svn_commit_info_t **com
   cb.info = commit_info_p;
   cb.pool = pool;
 
-  return svn_client_move6(src_paths, dst_path, force, move_as_child,
+  return svn_client_move6(src_paths, dst_path, move_as_child,
                           make_parents, revprop_table,
                           capture_commit_info, &cb, ctx, pool);
 }
@@ -637,6 +637,7 @@ svn_client_move4(svn_commit_info_t **com
     apr_array_make(pool, 1, sizeof(const char *));
   APR_ARRAY_PUSH(src_paths, const char *) = src_path;
 
+
   return svn_client_move5(commit_info_p, src_paths, dst_path, force, FALSE,
                           FALSE, NULL, ctx, pool);
 }
@@ -1010,8 +1011,8 @@ svn_client_diff_summarize_peg(const char
 /*** From export.c ***/
 svn_error_t *
 svn_client_export4(svn_revnum_t *result_rev,
-                   const char *from,
-                   const char *to,
+                   const char *from_path_or_url,
+                   const char *to_path,
                    const svn_opt_revision_t *peg_revision,
                    const svn_opt_revision_t *revision,
                    svn_boolean_t overwrite,
@@ -1021,15 +1022,15 @@ svn_client_export4(svn_revnum_t *result_
                    svn_client_ctx_t *ctx,
                    apr_pool_t *pool)
 {
-  return svn_client_export5(result_rev, from, to, peg_revision, revision,
-                            overwrite, ignore_externals, FALSE, depth,
-                            native_eol, ctx, pool);
+  return svn_client_export5(result_rev, from_path_or_url, to_path,
+                            peg_revision, revision, overwrite, ignore_externals,
+                            FALSE, depth, native_eol, ctx, pool);
 }
 
 svn_error_t *
 svn_client_export3(svn_revnum_t *result_rev,
-                   const char *from,
-                   const char *to,
+                   const char *from_path_or_url,
+                   const char *to_path,
                    const svn_opt_revision_t *peg_revision,
                    const svn_opt_revision_t *revision,
                    svn_boolean_t overwrite,
@@ -1039,16 +1040,16 @@ svn_client_export3(svn_revnum_t *result_
                    svn_client_ctx_t *ctx,
                    apr_pool_t *pool)
 {
-  return svn_client_export4(result_rev, from, to, peg_revision, revision,
-                            overwrite, ignore_externals,
+  return svn_client_export4(result_rev, from_path_or_url, to_path,
+                            peg_revision, revision, overwrite, ignore_externals,
                             SVN_DEPTH_INFINITY_OR_FILES(recurse),
                             native_eol, ctx, pool);
 }
 
 svn_error_t *
 svn_client_export2(svn_revnum_t *result_rev,
-                   const char *from,
-                   const char *to,
+                   const char *from_path_or_url,
+                   const char *to_path,
                    svn_opt_revision_t *revision,
                    svn_boolean_t force,
                    const char *native_eol,
@@ -1059,23 +1060,23 @@ svn_client_export2(svn_revnum_t *result_
 
   peg_revision.kind = svn_opt_revision_unspecified;
 
-  return svn_client_export3(result_rev, from, to, &peg_revision,
-                            revision, force, FALSE, TRUE,
+  return svn_client_export3(result_rev, from_path_or_url, to_path,
+                            &peg_revision, revision, force, FALSE, TRUE,
                             native_eol, ctx, pool);
 }
 
 
 svn_error_t *
 svn_client_export(svn_revnum_t *result_rev,
-                  const char *from,
-                  const char *to,
+                  const char *from_path_or_url,
+                  const char *to_path,
                   svn_opt_revision_t *revision,
                   svn_boolean_t force,
                   svn_client_ctx_t *ctx,
                   apr_pool_t *pool)
 {
-  return svn_client_export2(result_rev, from, to, revision, force, NULL, ctx,
-                            pool);
+  return svn_client_export2(result_rev, from_path_or_url, to_path, revision,
+                            force, NULL, ctx, pool);
 }
 
 /*** From list.c ***/
@@ -1337,6 +1338,27 @@ svn_client_log(const apr_array_header_t 
 /*** From merge.c ***/
 
 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)
+{
+  return svn_client_merge4(source1, revision1, source2, revision2,
+                           target_wcpath, depth, ignore_ancestry, force,
+                           record_only, dry_run, TRUE, merge_options,
+                           ctx, pool);
+}
+
+svn_error_t *
 svn_client_merge2(const char *source1,
                   const svn_opt_revision_t *revision1,
                   const char *source2,
@@ -1375,7 +1397,25 @@ svn_client_merge(const char *source1,
                            dry_run, NULL, ctx, pool);
 }
 
-
+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)
+{
+  return svn_client_merge_peg4(source, ranges_to_merge, peg_revision,
+                               target_wcpath, depth, ignore_ancestry, force,
+                               record_only, dry_run, TRUE, merge_options,
+                               ctx, pool);
+}
 
 svn_error_t *
 svn_client_merge_peg2(const char *source,
@@ -2039,3 +2079,18 @@ svn_client_mergeinfo_log_eligible(const 
                                   svn_depth_empty, revprops, ctx,
                                   pool);
 }
+
+/*** From relocate.c ***/
+svn_error_t *
+svn_client_relocate(const char *path,
+                    const char *from_prefix,
+                    const char *to_prefix,
+                    svn_boolean_t recurse,
+                    svn_client_ctx_t *ctx,
+                    apr_pool_t *pool)
+{
+  if (! recurse)
+    svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, 0,
+                     _("Non-recursive relocation not supported"));
+  return svn_client_relocate2(path, from_prefix, to_prefix, TRUE, ctx, pool);
+}

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_client/export.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_client/export.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_client/export.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_client/export.c Thu Nov  4 20:48:21 2010
@@ -300,7 +300,6 @@ copy_versioned_files(const char *from,
   const char *to_abspath;
   svn_node_kind_t from_kind;
   svn_depth_t node_depth;
-  int j;
   
   SVN_ERR(svn_dirent_get_absolute(&from_abspath, from, pool));
   SVN_ERR(svn_dirent_get_absolute(&to_abspath, to, pool));
@@ -350,6 +349,7 @@ copy_versioned_files(const char *from,
   if (from_kind == svn_node_dir)
     {
       apr_fileperms_t perm = APR_OS_DEFAULT;
+      int j;
 
       /* Try to make the new directory.  If this fails because the
          directory already exists, check our FORCE flag to see if we
@@ -929,8 +929,8 @@ close_file(void *file_baton,
 
 svn_error_t *
 svn_client_export5(svn_revnum_t *result_rev,
-                   const char *from,
-                   const char *to,
+                   const char *from_path_or_url,
+                   const char *to_path,
                    const svn_opt_revision_t *peg_revision,
                    const svn_opt_revision_t *revision,
                    svn_boolean_t overwrite,
@@ -947,15 +947,16 @@ svn_client_export5(svn_revnum_t *result_
   SVN_ERR_ASSERT(peg_revision != NULL);
   SVN_ERR_ASSERT(revision != NULL);
 
-  if (svn_path_is_url(to))
+  if (svn_path_is_url(to_path))
     return svn_error_return(svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                                               _("'%s' is not a local path"),
-                                              to));
+                                              to_path));
     
-  peg_revision = svn_cl__rev_default_to_head_or_working(peg_revision, from);
+  peg_revision = svn_cl__rev_default_to_head_or_working(peg_revision,
+                                                        from_path_or_url);
   revision = svn_cl__rev_default_to_peg(revision, peg_revision);
 
-  if (svn_path_is_url(from) ||
+  if (svn_path_is_url(from_path_or_url) ||
       ! SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(revision->kind))
     {
       svn_revnum_t revnum;
@@ -966,14 +967,14 @@ svn_client_export5(svn_revnum_t *result_
 
       /* Get the RA connection. */
       SVN_ERR(svn_client__ra_session_from_path(&ra_session, &revnum,
-                                               &url, from, NULL,
+                                               &url, from_path_or_url, NULL,
                                                peg_revision,
                                                revision, ctx, pool));
 
       /* Get the repository root. */
       SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url, pool));
 
-      eb->root_path = to;
+      eb->root_path = to_path;
       eb->root_url = url;
       eb->force = overwrite;
       eb->target_revision = &edit_revision;
@@ -993,6 +994,13 @@ svn_client_export5(svn_revnum_t *result_
           apr_hash_index_t *hi;
           struct file_baton *fb = apr_pcalloc(pool, sizeof(*fb));
 
+          if (svn_path_is_empty(to_path))
+            {
+              to_path = svn_path_uri_decode(svn_uri_basename(from_path_or_url,
+                                                             NULL), pool);
+              eb->root_path = to_path;
+            }
+          
           /* Since you cannot actually root an editor at a file, we
            * manually drive a few functions of our editor. */
 
@@ -1084,19 +1092,19 @@ svn_client_export5(svn_revnum_t *result_
            * So we just create the empty dir manually; but we do it via
            * open_root_internal(), in order to get proper notification.
            */
-          SVN_ERR(svn_io_check_path(to, &kind, pool));
+          SVN_ERR(svn_io_check_path(to_path, &kind, pool));
           if (kind == svn_node_none)
             SVN_ERR(open_root_internal
-                    (to, overwrite, ctx->notify_func2,
+                    (to_path, overwrite, ctx->notify_func2,
                      ctx->notify_baton2, pool));
 
           if (! ignore_externals && depth == svn_depth_infinity)
             {
               const char *to_abspath;
 
-              SVN_ERR(svn_dirent_get_absolute(&to_abspath, to, pool));
+              SVN_ERR(svn_dirent_get_absolute(&to_abspath, to_path, pool));
               SVN_ERR(svn_client__fetch_externals(eb->externals,
-                                                  from, to_abspath,
+                                                  from_path_or_url, to_abspath,
                                                   repos_root_url, depth, TRUE,
                                                   native_eol, &use_sleep,
                                                   ctx, pool));
@@ -1105,7 +1113,8 @@ svn_client_export5(svn_revnum_t *result_
       else if (kind == svn_node_none)
         {
           return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
-                                   _("URL '%s' doesn't exist"), from);
+                                   _("URL '%s' doesn't exist"),
+                                   from_path_or_url);
         }
       /* kind == svn_node_unknown not handled */
     }
@@ -1113,8 +1122,8 @@ svn_client_export5(svn_revnum_t *result_
     {
       /* This is a working copy export. */
       /* just copy the contents of the working copy into the target path. */
-      SVN_ERR(copy_versioned_files(from, to, revision, overwrite,
-                                   ignore_externals, ignore_keywords,
+      SVN_ERR(copy_versioned_files(from_path_or_url, to_path, revision,
+                                   overwrite, ignore_externals, ignore_keywords,
                                    depth, native_eol, ctx, pool));
     }
 
@@ -1122,7 +1131,7 @@ svn_client_export5(svn_revnum_t *result_
   if (ctx->notify_func2)
     {
       svn_wc_notify_t *notify
-        = svn_wc_create_notify(to,
+        = svn_wc_create_notify(to_path,
                                svn_wc_notify_update_completed, pool);
       notify->revision = edit_revision;
       (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_client/externals.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_client/externals.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_client/externals.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_client/externals.c Thu Nov  4 20:48:21 2010
@@ -205,7 +205,7 @@ switch_dir_external(const char *path,
                                                   revision, svn_depth_unknown,
                                                   FALSE, FALSE, FALSE,
                                                   timestamp_sleep, TRUE,
-                                                  TRUE, ctx, subpool));
+                                                  ctx, subpool));
               svn_pool_destroy(subpool);
               return SVN_NO_ERROR;
             }
@@ -229,8 +229,8 @@ switch_dir_external(const char *path,
                   SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root,
                                                  subpool));
 
-                  err = svn_client_relocate(path, repos_root_url, repos_root,
-                                            TRUE, ctx, subpool);
+                  err = svn_client_relocate2(path, repos_root_url, repos_root,
+                                             FALSE, ctx, subpool);
                   /* If the relocation failed because the new URL points
                      to another repository, then we need to relegate and
                      check out a new WC. */
@@ -576,7 +576,7 @@ resolve_relative_external_url(svn_wc_ext
                         pool,
                         url[2] == '/' ? "///" : "//",
                         svn_relpath_canonicalize(url+2, pool),
-                        NULL);
+                        (char *)NULL);
     }
   else if (svn_path_is_url(url) || *url == '/')
     {
@@ -697,7 +697,7 @@ resolve_relative_external_url(svn_wc_ext
                                                    scheme,
                                                    ":",
                                                    url,
-                                                   NULL),
+                                                   (char *)NULL),
                                        pool);
       return SVN_NO_ERROR;
     }

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_client/info.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_client/info.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_client/info.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_client/info.c Thu Nov  4 20:48:21 2010
@@ -167,6 +167,9 @@ build_info_for_entry(svn_info_t **info,
   SVN_ERR(svn_wc__node_get_schedule(&tmpinfo->schedule, NULL,
                                     wc_ctx, local_abspath, pool));
 
+  SVN_ERR(svn_wc_get_wc_root(&tmpinfo->wcroot_abspath, wc_ctx,
+                             local_abspath, pool, pool));
+
   /* Some random stuffs we don't have wc-ng apis for yet */
   SVN_ERR(svn_wc__node_get_info_bits(&tmpinfo->text_time,
                                      &tmpinfo->conflict_old,
@@ -289,7 +292,7 @@ push_dir_info(svn_ra_session_t *ra_sessi
       URL  = svn_path_url_add_component2(session_URL, name, subpool);
 
       fs_path = svn_uri_is_child(repos_root, URL, subpool);
-      fs_path = apr_pstrcat(subpool, "/", fs_path, NULL);
+      fs_path = apr_pstrcat(subpool, "/", fs_path, (char *)NULL);
       fs_path = svn_path_uri_decode(fs_path, subpool);
 
       lock = apr_hash_get(locks, fs_path, APR_HASH_KEY_STRING);
@@ -692,6 +695,8 @@ svn_info_dup(const svn_info_t *info, apr
     dupinfo->conflict_wrk = apr_pstrdup(pool, info->conflict_wrk);
   if (info->prejfile)
     dupinfo->prejfile = apr_pstrdup(pool, info->prejfile);
+  if (info->wcroot_abspath)
+    dupinfo->wcroot_abspath = apr_pstrdup(pool, info->wcroot_abspath);
 
   return dupinfo;
 }

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_client/list.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_client/list.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_client/list.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_client/list.c Thu Nov  4 20:48:21 2010
@@ -63,14 +63,23 @@ get_dir_contents(apr_uint32_t dirent_fie
   apr_hash_t *tmpdirents;
   apr_pool_t *iterpool = svn_pool_create(pool);
   apr_array_header_t *array;
+  svn_error_t *err;
   int i;
 
   if (depth == svn_depth_empty)
     return SVN_NO_ERROR;
 
-  /* Get the directory's entries, but not its props. */
-  SVN_ERR(svn_ra_get_dir2(ra_session, &tmpdirents, NULL, NULL,
-                          dir, rev, dirent_fields, pool));
+  /* Get the directory's entries, but not its props.  Ignore any
+     not-authorized errors.  */
+  err = svn_ra_get_dir2(ra_session, &tmpdirents, NULL, NULL,
+                        dir, rev, dirent_fields, pool);
+  if (err && ((err->apr_err == SVN_ERR_RA_NOT_AUTHORIZED) ||
+              (err->apr_err == SVN_ERR_RA_DAV_FORBIDDEN)))
+    {
+      svn_error_clear(err);
+      return SVN_NO_ERROR;
+    }
+  SVN_ERR(err);
 
   if (ctx->cancel_func)
     SVN_ERR(ctx->cancel_func(ctx->cancel_baton));

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_client/locking_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_client/locking_commands.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_client/locking_commands.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_client/locking_commands.c Thu Nov  4 20:48:21 2010
@@ -182,6 +182,23 @@ organize_lock_targets(const char **commo
   apr_hash_t *rel_targets_ret = apr_hash_make(pool);
   apr_pool_t *subpool = svn_pool_create(pool);
   svn_boolean_t url_mode;
+  svn_boolean_t wc_present = FALSE, url_present = FALSE;
+
+  /* Check to see if at least one of our paths is a working copy
+   * path or a repository url. */
+  for (i = 0; i < targets->nelts; ++i)
+    {
+      const char *target = APR_ARRAY_IDX(targets, i, const char *);
+      if (! svn_path_is_url(target))
+       wc_present = TRUE;
+      else
+       url_present = TRUE;
+    }
+
+  if (url_present && wc_present)
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("Cannot mix repository and working copy "
+                               "targets"));
 
   /* All targets must be either urls or paths */
 

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_client/merge.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_client/merge.c Thu Nov  4 20:48:21 2010
@@ -1121,8 +1121,6 @@ merge_props_changed(const char *local_di
      definition, 'svn merge' shouldn't touch any data within .svn/  */
   if (props->nelts)
     {
-      int i;
-
       /* If this is a forward merge then don't add new mergeinfo to
          PATH that is already part of PATH's own history, see
          http://svn.haxx.se/dev/archive-2008-09/0006.shtml.  If the
@@ -1150,6 +1148,8 @@ merge_props_changed(const char *local_di
          is having its existing mergeinfo deleted. */
       if (!merge_b->dry_run)
         {
+          int i;
+
           for (i = 0; i < props->nelts; ++i)
             {
               svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t);
@@ -1723,13 +1723,14 @@ merge_file_added(const char *local_dir_a
                    copying 'yours' to 'mine', isn't enough; we need to get
                    the whole text-base and props installed too, just as if
                    we had called 'svn cp wc wc'. */
-                /* ### would be nice to have cancel/notify funcs to pass */
                 SVN_ERR(svn_wc_add_repos_file4(
                             merge_b->ctx->wc_ctx, mine_abspath,
                             new_base_contents, new_contents,
                             new_base_props, new_props,
                             copyfrom_url, copyfrom_rev,
-                            NULL, NULL, NULL, NULL, subpool));
+                            merge_b->ctx->cancel_func,
+                            merge_b->ctx->cancel_baton,
+                            subpool));
 
                 /* ### delete 'yours' ? */
               }
@@ -3778,8 +3779,8 @@ filter_merged_revisions(svn_client__merg
             child->remaining_ranges = svn_rangelist_dup(explicit_rangelist,
                                                         pool);
         }
-    }
 #endif
+    }
 
   svn_pool_destroy(subpool);
   return SVN_NO_ERROR;
@@ -6596,7 +6597,6 @@ do_file_merge(svn_mergeinfo_catalog_t re
   svn_merge_range_t range;
   svn_mergeinfo_t target_mergeinfo;
   svn_merge_range_t *conflicted_range = NULL;
-  int i;
   svn_boolean_t indirect = FALSE;
   apr_pool_t *subpool;
   svn_boolean_t is_rollback = (revision1 > revision2);
@@ -6676,6 +6676,7 @@ do_file_merge(svn_mergeinfo_catalog_t re
   if (!merge_b->record_only)
     {
       apr_array_header_t *ranges_to_merge = remaining_ranges;
+      int i;
 
       /* If we have ancestrally related sources and more than one
          range to merge, eliminate no-op ranges before going through
@@ -8028,7 +8029,18 @@ do_directory_merge(svn_mergeinfo_catalog
                    apr_pool_t *pool)
 {
   svn_error_t *err = SVN_NO_ERROR;
+
+  /* The range defining the mergeinfo we will record to describe the merge
+     (assuming we are recording mergeinfo
+
+     Note: This may be a subset of REVISION1:REVISION2 if
+     populate_remaining_ranges() determines that some part of
+     REVISION1:REVISION2 has already been wholly merged to TARGET_ABSPATH.
+     Also, the actual editor drive(s) may be a subset of RANGE, if
+     remove_noop_subtree_ranges() and/or fix_deleted_subtree_ranges()
+     further tweak things. */
   svn_merge_range_t range;
+
   svn_ra_session_t *ra_session;
   svn_client__merge_path_t *target_merge_path;
   svn_boolean_t is_rollback = (revision1 > revision2);
@@ -8101,17 +8113,22 @@ do_directory_merge(svn_mergeinfo_catalog
 
   if (honor_mergeinfo && !merge_b->reintegrate_merge)
     {
-      svn_revnum_t start_rev, end_rev;
+      svn_revnum_t new_range_start, start_rev, end_rev;
       apr_pool_t *iterpool = svn_pool_create(pool);
 
-      /* The merge target target_wcpath and/or its subtrees may not need all
+      /* The merge target TARGET_ABSPATH and/or its subtrees may not need all
          of REVISION1:REVISION2 applied.  So examine
          NOTIFY_B->CHILDREN_WITH_MERGEINFO to find the oldest starting
          revision that actually needs to be merged (for reverse merges this is
-         the youngest starting revision). */
-      start_rev =
-        get_most_inclusive_start_rev(notify_b->children_with_mergeinfo,
-                                     is_rollback);
+         the youngest starting revision).
+         
+         We'll do this twice, right now for the start of the mergeinfo we will
+         ultimately record to describe this merge and then later for the 
+         start of the actual editor drive. */
+      new_range_start = get_most_inclusive_start_rev(
+        notify_b->children_with_mergeinfo, is_rollback);
+      if (SVN_IS_VALID_REVNUM(new_range_start))
+        range.start = new_range_start;
 
       /* Remove inoperative ranges from any subtrees' remaining_ranges
          to spare the expense of noop editor drives. */
@@ -8121,16 +8138,20 @@ do_directory_merge(svn_mergeinfo_catalog
                                            notify_b, merge_b,
                                            pool, iterpool));
 
+      /* Adjust subtrees' remaining_ranges to deal with issue #3067 */
       SVN_ERR(fix_deleted_subtree_ranges(url1, revision1, url2, revision2,
                                          ra_session, notify_b, merge_b, pool));
 
+      /* remove_noop_subtree_ranges() and/or fix_deleted_subtree_range()
+         may have further refined the starting revision for our editor
+         drive. */
+      start_rev =
+        get_most_inclusive_start_rev(notify_b->children_with_mergeinfo,
+                                     is_rollback);
+
       /* Is there anything to merge? */
       if (SVN_IS_VALID_REVNUM(start_rev))
         {
-          /* Adjust range to describe the start of our most
-             inclusive merge. */
-          range.start = start_rev;
-
           /* Now examine NOTIFY_B->CHILDREN_WITH_MERGEINFO to find the youngest
              ending revision that actually needs to be merged (for reverse
              merges this is the oldest starting revision). */
@@ -8170,6 +8191,33 @@ do_directory_merge(svn_mergeinfo_catalog
               svn_revnum_t next_end_rev;
               const char *real_url1 = url1, *real_url2 = url2;
               const char *old_sess1_url = NULL, *old_sess2_url = NULL;
+              svn_merge_range_t *first_target_range = APR_ARRAY_IDX(
+                target_merge_path->remaining_ranges, 0, svn_merge_range_t *);
+
+              /* Issue #3324: Stop editor abuse!  Don't call
+                 drive_merge_report_editor() in such a way that we request an
+                 editor with svn_client__get_diff_editor() for some rev X,
+                 then call svn_ra_do_diff3() for some revision Y, and then
+                 call reporter->set_path(PATH=="") to set the root revision
+                 for the editor drive to revision Z where
+                 (X != Z && X < Z < Y).  This is bogus because the server will
+                 send us the diff between X:Y but the client is expecting the
+                 diff between Y:Z.  See issue #3324 for full details on the
+                 problems this can cause. */
+              if (first_target_range
+                  && start_rev != first_target_range->start)
+                {
+                  if (is_rollback)
+                    {
+                      if (end_rev < first_target_range->start)
+                        end_rev = first_target_range->start;
+                    }
+                  else
+                    {
+                      if (end_rev > first_target_range->start)
+                        end_rev = first_target_range->start;
+                    }
+                }
 
               svn_pool_clear(iterpool);
 
@@ -8815,6 +8863,73 @@ merge_cousins_and_supplement_mergeinfo(c
   return SVN_NO_ERROR;
 }
 
+/* Perform checks to determine whether of the working copy at TARGET_ABSPATH
+ * can safely be used as a merge target. Checks are performed according to
+ * the ALLOW_MIXED_REV, ALLOW_LOCAL_MODS, and ALLOW_SWITCHED_SUBTREES
+ * parameters. If any checks fail, raise SVN_ERR_CLIENT_NOT_READY_TO_MERGE.
+ *
+ * E.g. if all the ALLOW_* parameters are FALSE, TARGET_ABSPATH must
+ * be a single-revision, pristine, unswitched working copy.
+ * In other words, it must reflect a subtree of the repostiory as found
+ * at single revision -- although sparse checkouts are permitted. */
+static svn_error_t *
+ensure_wc_is_suitable_merge_target(const char *target_abspath,
+                                   svn_client_ctx_t *ctx,
+                                   svn_boolean_t allow_mixed_rev,
+                                   svn_boolean_t allow_local_mods,
+                                   svn_boolean_t allow_switched_subtrees,
+                                   apr_pool_t *scratch_pool)
+{
+  svn_wc_revision_status_t *wc_stat;
+
+  /* Avoid the following status crawl if we don't need it. */
+  if (allow_mixed_rev && allow_local_mods && allow_switched_subtrees)
+    return SVN_NO_ERROR;
+
+  /* Get a WC summary with min/max revisions set to the BASE revision. */
+  SVN_ERR(svn_wc_revision_status2(&wc_stat, ctx->wc_ctx, target_abspath, NULL,
+                                  FALSE, ctx->cancel_func, ctx->cancel_baton,
+                                  scratch_pool, scratch_pool));
+
+  if (! allow_switched_subtrees && wc_stat->switched)
+    return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
+                            _("Cannot merge into a working copy "
+                              "with a switched subtree"));
+
+  if (! allow_local_mods && wc_stat->modified)
+    return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
+                            _("Cannot merge into a working copy "
+                              "that has local modifications"));
+
+  if (! allow_mixed_rev)
+    {
+      if (! (SVN_IS_VALID_REVNUM(wc_stat->min_rev)
+             && SVN_IS_VALID_REVNUM(wc_stat->max_rev)))
+        {
+          svn_boolean_t is_added;
+
+          /* Allow merge into added nodes. */
+          SVN_ERR(svn_wc__node_is_added(&is_added, ctx->wc_ctx, target_abspath,
+                                        scratch_pool));
+          if (is_added)
+            return SVN_NO_ERROR;
+          else
+            return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
+                                    _("Cannot determine revision of working "
+                                      "copy"));
+        }
+
+      if (wc_stat->min_rev != wc_stat->max_rev)
+        return svn_error_createf(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
+                                 _("Cannot merge into mixed-revision working "
+                                   "copy [%lu:%lu]; try updating first"),
+                                   wc_stat->min_rev, wc_stat->max_rev);
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
 /*-----------------------------------------------------------------------*/
 
 /*** Public APIs ***/
@@ -8830,6 +8945,7 @@ merge_locked(const char *source1,
              svn_boolean_t force,
              svn_boolean_t record_only,
              svn_boolean_t dry_run,
+             svn_boolean_t allow_mixed_rev,
              const apr_array_header_t *merge_options,
              svn_client_ctx_t *ctx,
              apr_pool_t *scratch_pool)
@@ -8905,6 +9021,12 @@ merge_locked(const char *source1,
                               _("Merge target '%s' does not exist in the "
                                 "working copy"), target_abspath));
 
+
+  /* Do not allow merges into mixed-revision working copies. */
+  SVN_ERR(ensure_wc_is_suitable_merge_target(target_abspath, ctx,
+                                             allow_mixed_rev, TRUE, TRUE,
+                                             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,
@@ -9103,6 +9225,7 @@ struct merge_baton {
   svn_boolean_t force;
   svn_boolean_t record_only;
   svn_boolean_t dry_run;
+  svn_boolean_t allow_mixed_rev;
   const apr_array_header_t *merge_options;
   svn_client_ctx_t *ctx;
 };
@@ -9116,7 +9239,8 @@ merge_cb(void *baton, apr_pool_t *result
   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));
+                       b->allow_mixed_rev, b->merge_options, b->ctx,
+                       scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -9144,7 +9268,7 @@ get_target_and_lock_abspath(const char *
 }
 
 svn_error_t *
-svn_client_merge3(const char *source1,
+svn_client_merge4(const char *source1,
                   const svn_opt_revision_t *revision1,
                   const char *source2,
                   const svn_opt_revision_t *revision2,
@@ -9154,6 +9278,7 @@ svn_client_merge3(const char *source1,
                   svn_boolean_t force,
                   svn_boolean_t record_only,
                   svn_boolean_t dry_run,
+                  svn_boolean_t allow_mixed_rev,
                   const apr_array_header_t *merge_options,
                   svn_client_ctx_t *ctx,
                   apr_pool_t *pool)
@@ -9174,6 +9299,7 @@ svn_client_merge3(const char *source1,
   baton.force = force;
   baton.record_only = record_only;
   baton.dry_run = dry_run;
+  baton.allow_mixed_rev = allow_mixed_rev;
   baton.merge_options = merge_options;
   baton.ctx = ctx;
 
@@ -9188,45 +9314,6 @@ svn_client_merge3(const char *source1,
 }
 
 
-/* If TARGET_WCPATH does not reflect a single-revision, pristine,
-   unswitched working copy -- in other words, a subtree found in a
-   single revision (although sparse checkouts are permitted) -- raise
-   SVN_ERR_CLIENT_NOT_READY_TO_MERGE. */
-static svn_error_t *
-ensure_wc_reflects_repository_subtree(const char *target_abspath,
-                                      svn_client_ctx_t *ctx,
-                                      apr_pool_t *scratch_pool)
-{
-  svn_wc_revision_status_t *wc_stat;
-
-  /* Get a WC summary with min/max revisions set to the BASE revision. */
-  SVN_ERR(svn_wc_revision_status2(&wc_stat, ctx->wc_ctx, target_abspath, NULL,
-                                  FALSE, ctx->cancel_func, ctx->cancel_baton,
-                                  scratch_pool, scratch_pool));
-
-  if (wc_stat->switched)
-    return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
-                            _("Cannot reintegrate into a working copy "
-                              "with a switched subtree"));
-
-  if (wc_stat->modified)
-    return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
-                            _("Cannot reintegrate into a working copy "
-                              "that has local modifications"));
-
-  if (! (SVN_IS_VALID_REVNUM(wc_stat->min_rev)
-         && SVN_IS_VALID_REVNUM(wc_stat->max_rev)))
-    return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
-                            _("Cannot determine revision of working copy"));
-
-  if (wc_stat->min_rev != wc_stat->max_rev)
-    return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE, NULL,
-                            _("Cannot reintegrate into mixed-revision "
-                              "working copy; try updating first"));
-
-  return SVN_NO_ERROR;
-}
-
 /* Check if mergeinfo for a given path is described explicitly or via
    inheritance in a mergeinfo catalog.
 
@@ -10174,8 +10261,11 @@ merge_reintegrate_locked(const char *sou
                              svn_dirent_local_style(target_abspath,
                                                     scratch_pool));
 
-  SVN_ERR(ensure_wc_reflects_repository_subtree(target_abspath, ctx,
-                                                scratch_pool));
+  /* A reintegrate merge requires the merge target to reflect a subtree
+   * of the repository as found at a single revision. */
+  SVN_ERR(ensure_wc_is_suitable_merge_target(target_abspath, ctx,
+                                             FALSE, FALSE, FALSE,
+                                             scratch_pool));
   SVN_ERR(svn_wc__node_get_base_rev(&target_base_rev, ctx->wc_ctx,
                                     target_abspath, scratch_pool));
 
@@ -10391,6 +10481,7 @@ merge_peg_locked(const char *source,
                  svn_boolean_t force,
                  svn_boolean_t record_only,
                  svn_boolean_t dry_run,
+                 svn_boolean_t allow_mixed_rev,
                  const apr_array_header_t *merge_options,
                  svn_client_ctx_t *ctx,
                  apr_pool_t *scratch_pool)
@@ -10432,6 +10523,10 @@ merge_peg_locked(const char *source,
                               _("Merge target '%s' does not exist in the "
                                 "working copy"), target_abspath));
 
+  SVN_ERR(ensure_wc_is_suitable_merge_target(target_abspath, ctx,
+                                             allow_mixed_rev, TRUE, TRUE,
+                                             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,
@@ -10494,6 +10589,7 @@ struct merge_peg_baton {
   svn_boolean_t force;
   svn_boolean_t record_only;
   svn_boolean_t dry_run;
+  svn_boolean_t allow_mixed_rev;
   const apr_array_header_t *merge_options;
   svn_client_ctx_t *ctx;
 };
@@ -10507,13 +10603,14 @@ merge_peg_cb(void *baton, apr_pool_t *re
   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));
+                           b->allow_mixed_rev, b->merge_options, b->ctx,
+                           scratch_pool));
 
   return SVN_NO_ERROR;
 }
 
 svn_error_t *
-svn_client_merge_peg3(const char *source,
+svn_client_merge_peg4(const char *source,
                       const apr_array_header_t *ranges_to_merge,
                       const svn_opt_revision_t *peg_revision,
                       const char *target_wcpath,
@@ -10522,6 +10619,7 @@ svn_client_merge_peg3(const char *source
                       svn_boolean_t force,
                       svn_boolean_t record_only,
                       svn_boolean_t dry_run,
+                      svn_boolean_t allow_mixed_rev,
                       const apr_array_header_t *merge_options,
                       svn_client_ctx_t *ctx,
                       apr_pool_t *pool)
@@ -10545,6 +10643,7 @@ svn_client_merge_peg3(const char *source
   baton.force = force;
   baton.record_only = record_only;
   baton.dry_run = dry_run;
+  baton.allow_mixed_rev = allow_mixed_rev;
   baton.merge_options = merge_options;
   baton.ctx = ctx;
 

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_client/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_client/mergeinfo.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_client/mergeinfo.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_client/mergeinfo.c Thu Nov  4 20:48:21 2010
@@ -672,7 +672,7 @@ svn_client__mergeinfo_from_segments(svn_
         continue;
 
       /* Prepend a leading slash to our path. */
-      source_path = apr_pstrcat(pool, "/", segment->path, NULL);
+      source_path = apr_pstrcat(pool, "/", segment->path, (char *)NULL);
 
       /* See if we already stored ranges for this path.  If not, make
          a new list.  */
@@ -1258,11 +1258,12 @@ static svn_mergeinfo_t
 find_nearest_ancestor(const apr_array_header_t *depth_first_catalog_index,
                       const char *abs_repos_path)
 {
-  int i;
   int ancestor_index = -1;
 
   if (depth_first_catalog_index)
     {
+      int i;
+
       for (i = 0; i < depth_first_catalog_index->nelts; i++)
         {
           svn_sort__item_t item = APR_ARRAY_IDX(depth_first_catalog_index, i,

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_client/patch.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_client/patch.c Thu Nov  4 20:48:21 2010
@@ -346,9 +346,7 @@ resolve_target_path(patch_target_t *targ
   target->canon_path_from_patchfile = svn_dirent_internal_style(
                                         path_from_patchfile, result_pool);
 
-  /* We allow properties to be set on the wc root dir.
-   * ### Do we need to check for empty paths here, shouldn't the parser
-   * ### guarentee that the paths returned are non-empty? */
+  /* We allow properties to be set on the wc root dir. */
   if (! prop_changes_only && target->canon_path_from_patchfile[0] == '\0')
     {
       /* An empty patch target path? What gives? Skip this. */
@@ -498,7 +496,7 @@ init_prop_target(prop_patch_target_t **p
   new_prop_target->content_info = content_info;
 
   err = svn_wc_prop_get2(&value, wc_ctx, local_abspath, prop_name, 
-                           result_pool, scratch_pool);
+                         result_pool, scratch_pool);
   if (err)
     {
       if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
@@ -528,12 +526,40 @@ init_prop_target(prop_patch_target_t **p
   return SVN_NO_ERROR;
 }
 
+/* Return a suitable filename for the target of PATCH.
+ * Examine the ``old'' and ``new'' file names, and choose the file name
+ * with the fewest path components, the shortest basename, and the shortest
+ * total file name length (in that order). In case of a tie, return the new
+ * filename. This heuristic is also used by Larry Wall's UNIX patch (except
+ * that it prompts for a filename in case of a tie). */
+static const char *
+choose_target_filename(const svn_patch_t *patch)
+{
+  apr_size_t old;
+  apr_size_t new;
+
+  old = svn_path_component_count(patch->old_filename);
+  new = svn_path_component_count(patch->new_filename);
+
+  if (old == new)
+    {
+      old = strlen(svn_dirent_basename(patch->old_filename, NULL));
+      new = strlen(svn_dirent_basename(patch->new_filename, NULL));
+
+      if (old == new)
+        {
+          old = strlen(patch->old_filename);
+          new = strlen(patch->new_filename);
+        }
+    }
+
+  return (old < new) ? patch->old_filename : patch->new_filename;
+}
+
 /* Attempt to initialize a *PATCH_TARGET structure for a target file
  * described by PATCH. Use working copy context WC_CTX.
  * STRIP_COUNT specifies the number of leading path components
  * which should be stripped from target paths in the patch.
- * OLD_PATCH_TARGET_NAMES indicates whether the old target's name parsed
- * from the patch file should be preferred over the new target's name.
  * The patch target structure is allocated in RESULT_POOL, but if the target
  * should be skipped, PATCH_TARGET->SKIPPED is set and the target should be
  * treated as not fully initialized, e.g. the caller should not not do any
@@ -545,9 +571,7 @@ static svn_error_t *
 init_patch_target(patch_target_t **patch_target,
                   const svn_patch_t *patch,
                   const char *base_dir,
-                  svn_wc_context_t *wc_ctx,
-                  int strip_count,
-                  svn_boolean_t old_patch_target_names,
+                  svn_wc_context_t *wc_ctx, int strip_count,
                   svn_boolean_t remove_tempfiles,
                   apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
@@ -593,8 +617,7 @@ init_patch_target(patch_target_t **patch
   target->prop_targets = apr_hash_make(result_pool);
   target->pool = result_pool;
 
-  SVN_ERR(resolve_target_path(target, old_patch_target_names ?
-                                patch->old_filename : patch->new_filename,
+  SVN_ERR(resolve_target_path(target, choose_target_filename(patch),
                               base_dir, strip_count, prop_changes_only,
                               wc_ctx, result_pool, scratch_pool));
   if (! target->skipped)
@@ -631,13 +654,16 @@ init_patch_target(patch_target_t **patch
                                                    scratch_pool));
         }
 
-      /* ### Is it ok to set target->added here? Isn't the target supposed to
-       * ### be marked as added after it's been proven that it can be added?
-       * ### One alternative is to include a git_added flag. Or maybe we
-       * ### should have kept the patch field in patch_target_t? Then we
-       * ### could have checked for target->patch->operation == added */
+      /* ### Is it ok to set the operation of the target already here? Isn't
+       * ### the target supposed to be marked with an operation after we have
+       * ### determined that the changes will apply cleanly to the WC? Maybe
+       * ### we should have kept the patch field in patch_target_t to be
+       * ### able to distinguish between 'what the patch says we should do' 
+       * ### and 'what we can do with the given state of our WC'. */
       if (patch->operation == svn_diff_op_added)
         target->added = TRUE;
+      else if (patch->operation == svn_diff_op_deleted)
+        target->deleted = TRUE;
 
       SVN_ERR(svn_stream_open_unique(&patched_raw,
                                      &target->patched_path, NULL,
@@ -862,59 +888,41 @@ match_hunk(svn_boolean_t *matched, targe
                                            NULL, FALSE,
                                            content_info->keywords, FALSE,
                                            iterpool));
-      lines_read++;
       SVN_ERR(read_line(content_info, &target_line, iterpool, iterpool));
-      if (! hunk_eof)
+
+      lines_read++;
+
+      /* If the last line doesn't have a newline, we get EOF but still
+       * have a non-empty line to compare. */
+      if ((hunk_eof && hunk_line->len == 0) ||
+          (content_info->eof && *target_line == 0))
+        break;
+
+      /* Leading/trailing fuzzy lines always match. */
+      if ((lines_read <= fuzz && leading_context > fuzz) ||
+          (lines_read > hunk_length - fuzz && trailing_context > fuzz))
+        lines_matched = TRUE;
+      else
         {
-          if (lines_read <= fuzz && leading_context > fuzz)
-            lines_matched = TRUE;
-          else if (lines_read > hunk_length - fuzz &&
-                   trailing_context > fuzz)
-            lines_matched = TRUE;
-          else
+          if (ignore_whitespace)
             {
-              if (ignore_whitespace)
-                {
-                  char *stripped_hunk_line = apr_pstrdup(pool,
-                                                         hunk_line_translated);
-                  char *stripped_target_line = apr_pstrdup(pool, target_line);
-
-                  apr_collapse_spaces(stripped_hunk_line,
-                                      hunk_line_translated);
-                  apr_collapse_spaces(stripped_target_line, target_line);
-                  lines_matched = ! strcmp(stripped_hunk_line,
-                                           stripped_target_line);
-                }
-              else 
-                lines_matched = ! strcmp(hunk_line_translated, target_line);
+              char *hunk_line_trimmed;
+              char *target_line_trimmed;
+
+              hunk_line_trimmed = apr_pstrdup(iterpool, hunk_line_translated);
+              target_line_trimmed = apr_pstrdup(iterpool, target_line);
+              apr_collapse_spaces(hunk_line_trimmed, hunk_line_trimmed);
+              apr_collapse_spaces(target_line_trimmed, target_line_trimmed);
+              lines_matched = ! strcmp(hunk_line_trimmed, target_line_trimmed);
             }
+          else
+            lines_matched = ! strcmp(hunk_line_translated, target_line);
         }
     }
-  while (lines_matched && ! (hunk_eof || content_info->eof));
+  while (lines_matched);
 
-  if (hunk_eof)
-    *matched = lines_matched;
-  else if (content_info->eof)
-    {
-      /* If the target has no newline at end-of-file, we get an EOF
-       * indication for the target earlier than we do get it for the hunk. */
-      if (match_modified)
-        SVN_ERR(svn_diff_hunk_readline_modified_text(hunk, &hunk_line,
-                                                     NULL, &hunk_eof,
-                                                     iterpool, iterpool));
-      else
-        SVN_ERR(svn_diff_hunk_readline_original_text(hunk, &hunk_line,
-                                                     NULL, &hunk_eof,
-                                                     iterpool, iterpool));
+  *matched = lines_matched && hunk_eof && hunk_line->len == 0;
 
-      /* When comparing modified text we require that all lines match, else
-       * a hunk that adds a newline at the end will be treated as already
-       * applied even if it isn't. */
-      if (! match_modified && hunk_line->len == 0 && hunk_eof)
-        *matched = lines_matched;
-      else
-        *matched = FALSE;
-    }
   SVN_ERR(seek_to_line(content_info, saved_line, iterpool));
 
   svn_pool_destroy(iterpool);
@@ -954,7 +962,6 @@ scan_for_match(svn_linenum_t *matched_li
          ! content_info->eof)
     {
       svn_boolean_t matched;
-      int i;
 
       svn_pool_clear(iterpool);
 
@@ -966,6 +973,7 @@ scan_for_match(svn_linenum_t *matched_li
       if (matched)
         {
           svn_boolean_t taken = FALSE;
+          int i;
 
           /* Don't allow hunks to match at overlapping locations. */
           for (i = 0; i < content_info->hunks->nelts; i++)
@@ -1160,54 +1168,55 @@ get_hunk_info(hunk_info_t **hi, patch_ta
   else if (original_start > 0 && content_info->stream)
     {
       svn_linenum_t saved_line = content_info->current_line;
-      svn_linenum_t modified_start;
 
-      /* Check if the hunk is already applied.
-       * We only check for an exact match here, and don't bother checking
-       * for already applied patches with offset/fuzz, because such a
-       * check would be ambiguous. */
-      if (fuzz == 0)
+      /* Scan for a match at the line where the hunk thinks it
+       * should be going. */
+      SVN_ERR(seek_to_line(content_info, original_start, scratch_pool));
+      if (content_info->current_line != original_start)
         {
-          modified_start = svn_diff_hunk_get_modified_start(hunk);
-          if (modified_start == 0)
-            {
-              /* Patch wants to delete the file. */
-              already_applied = target->locally_deleted;
-            }
-          else
-            {
-              SVN_ERR(seek_to_line(content_info, modified_start,
-                                   scratch_pool));
-              SVN_ERR(scan_for_match(&matched_line, content_info,
-                                     hunk, TRUE,
-                                     modified_start + 1,
-                                     fuzz, ignore_whitespace, TRUE,
-                                     cancel_func, cancel_baton,
-                                     scratch_pool));
-              already_applied = (matched_line == modified_start);
-            }
+          /* Seek failed. */
+          matched_line = 0;
         }
       else
-        already_applied = FALSE;
+        SVN_ERR(scan_for_match(&matched_line, content_info, hunk, TRUE,
+                               original_start + 1, fuzz,
+                               ignore_whitespace, FALSE,
+                               cancel_func, cancel_baton,
+                               scratch_pool));
 
-      if (! already_applied)
+      if (matched_line != original_start)
         {
-          /* Scan for a match at the line where the hunk thinks it
-           * should be going. */
-          SVN_ERR(seek_to_line(content_info, original_start, scratch_pool));
-          if (content_info->current_line != original_start)
+          /* Check if the hunk is already applied.
+           * We only check for an exact match here, and don't bother checking
+           * for already applied patches with offset/fuzz, because such a
+           * check would be ambiguous. */
+          if (fuzz == 0)
             {
-              /* Seek failed. */
-              matched_line = 0;
+              svn_linenum_t modified_start;
+
+              modified_start = svn_diff_hunk_get_modified_start(hunk);
+              if (modified_start == 0)
+                {
+                  /* Patch wants to delete the file. */
+                  already_applied = target->locally_deleted;
+                }
+              else
+                {
+                  SVN_ERR(seek_to_line(content_info, modified_start,
+                                       scratch_pool));
+                  SVN_ERR(scan_for_match(&matched_line, content_info,
+                                         hunk, TRUE,
+                                         modified_start + 1,
+                                         fuzz, ignore_whitespace, TRUE,
+                                         cancel_func, cancel_baton,
+                                         scratch_pool));
+                  already_applied = (matched_line == modified_start);
+                }
             }
           else
-            SVN_ERR(scan_for_match(&matched_line, content_info, hunk, TRUE,
-                                   original_start + 1, fuzz,
-                                   ignore_whitespace, FALSE,
-                                   cancel_func, cancel_baton,
-                                   scratch_pool));
+            already_applied = FALSE;
 
-          if (matched_line != original_start)
+          if (! already_applied)
             {
               /* Scan the whole file again from the start. */
               SVN_ERR(seek_to_line(content_info, 1, scratch_pool));
@@ -1252,24 +1261,6 @@ get_hunk_info(hunk_info_t **hi, patch_ta
   return SVN_NO_ERROR;
 }
 
-/* Attempt to write LEN bytes of DATA to STREAM, the underlying file
- * of which is at ABSPATH. Fail if not all bytes could be written to
- * the stream. Do temporary allocations in POOL. */
-static svn_error_t *
-try_stream_write(svn_stream_t *stream, const char *abspath,
-                 const char *data, apr_size_t len, apr_pool_t *pool)
-{
-  apr_size_t written;
-
-  written = len;
-  SVN_ERR(svn_stream_write(stream, data, &written));
-  if (written != len)
-    return svn_error_createf(SVN_ERR_IO_WRITE_ERROR, NULL,
-                             _("Error writing to '%s'"),
-                             svn_dirent_local_style(abspath, pool));
-  return SVN_NO_ERROR;
-}
-
 /* Copy lines to the patched stream until the specified LINE has been
  * reached. Indicate in *EOF whether end-of-file was encountered while
  * reading from the target.
@@ -1286,28 +1277,29 @@ copy_lines_to_target(target_content_info
          && ! content_info->eof)
     {
       const char *target_line;
+      apr_size_t len;
 
       svn_pool_clear(iterpool);
 
       SVN_ERR(read_line(content_info, &target_line, iterpool, iterpool));
       if (! content_info->eof)
         target_line = apr_pstrcat(iterpool, target_line, content_info->eol_str,
-                                  NULL);
-
-      SVN_ERR(try_stream_write(content_info->patched, patched_path,
-                               target_line, strlen(target_line), iterpool));
+                                  (char *)NULL);
+      len = strlen(target_line);
+      SVN_ERR(svn_stream_write(content_info->patched, target_line, &len));
     }
   svn_pool_destroy(iterpool);
 
   return SVN_NO_ERROR;
 }
 
-/* Write the diff text of the hunk described by HI to the
- * reject stream of CONTENT_INFO, and mark TARGET as having had rejects.
+/* Write the diff text of HUNK to the reject stream of CONTENT_INFO,
+ * and mark TARGET as having had rejects.
  * Do temporary allocations in POOL. */
 static svn_error_t *
 reject_hunk(patch_target_t *target, target_content_info_t *content_info, 
-            hunk_info_t *hi, const char *prop_name, apr_pool_t *pool)
+            const svn_diff_hunk_t *hunk, const char *prop_name,
+            apr_pool_t *pool)
 {
   const char *hunk_header;
   apr_size_t len;
@@ -1328,18 +1320,18 @@ reject_hunk(patch_target_t *target, targ
       /* ### What about just setting a variable to either "@@" or "##",
        * ### and merging with the else clause below? */
       hunk_header = apr_psprintf(pool, "## -%lu,%lu +%lu,%lu ##%s",
-                                 svn_diff_hunk_get_original_start(hi->hunk),
-                                 svn_diff_hunk_get_original_length(hi->hunk),
-                                 svn_diff_hunk_get_modified_start(hi->hunk),
-                                 svn_diff_hunk_get_modified_length(hi->hunk),
+                                 svn_diff_hunk_get_original_start(hunk),
+                                 svn_diff_hunk_get_original_length(hunk),
+                                 svn_diff_hunk_get_modified_start(hunk),
+                                 svn_diff_hunk_get_modified_length(hunk),
                                  APR_EOL_STR);
     }
   else
     hunk_header = apr_psprintf(pool, "@@ -%lu,%lu +%lu,%lu @@%s",
-                               svn_diff_hunk_get_original_start(hi->hunk),
-                               svn_diff_hunk_get_original_length(hi->hunk),
-                               svn_diff_hunk_get_modified_start(hi->hunk),
-                               svn_diff_hunk_get_modified_length(hi->hunk),
+                               svn_diff_hunk_get_original_start(hunk),
+                               svn_diff_hunk_get_original_length(hunk),
+                               svn_diff_hunk_get_modified_start(hunk),
+                               svn_diff_hunk_get_modified_length(hunk),
                                APR_EOL_STR);
   len = strlen(hunk_header);
   SVN_ERR(svn_stream_write(content_info->reject, hunk_header, &len));
@@ -1352,17 +1344,22 @@ reject_hunk(patch_target_t *target, targ
 
       svn_pool_clear(iterpool);
 
-      SVN_ERR(svn_diff_hunk_readline_diff_text(hi->hunk, &hunk_line, &eol_str,
+      SVN_ERR(svn_diff_hunk_readline_diff_text(hunk, &hunk_line, &eol_str,
                                                &eof, iterpool, iterpool));
       if (! eof)
         {
           if (hunk_line->len >= 1)
-            SVN_ERR(try_stream_write(content_info->reject, target->reject_path,
-                                     hunk_line->data, hunk_line->len,
-                                     iterpool));
+            {
+              len = hunk_line->len;
+              SVN_ERR(svn_stream_write(content_info->reject, hunk_line->data,
+                                       &len));
+            }
+
           if (eol_str)
-            SVN_ERR(try_stream_write(content_info->reject, target->reject_path,
-                                     eol_str, strlen(eol_str), iterpool));
+            {
+              len = strlen(eol_str);
+              SVN_ERR(svn_stream_write(content_info->reject, eol_str, &len));
+            }
         }
     }
   while (! eof);
@@ -1411,7 +1408,7 @@ apply_hunk(patch_target_t *target, targe
         {
           /* Seek failed, reject this hunk. */
           hi->rejected = TRUE;
-          SVN_ERR(reject_hunk(target, content_info, hi, prop_name, pool));
+          SVN_ERR(reject_hunk(target, content_info, hi->hunk, prop_name, pool));
           return SVN_NO_ERROR;
         }
     }
@@ -1435,11 +1432,15 @@ apply_hunk(patch_target_t *target, targe
       if (! eof && lines_read > hi->fuzz &&
           lines_read <= svn_diff_hunk_get_modified_length(hi->hunk) - hi->fuzz)
         {
+          apr_size_t len;
+
           if (hunk_line->len >= 1)
-            SVN_ERR(try_stream_write(content_info->patched, 
-                                     target->patched_path,
-                                     hunk_line->data, hunk_line->len,
-                                     iterpool));
+            {
+              len = hunk_line->len;
+              SVN_ERR(svn_stream_write(content_info->patched, hunk_line->data,
+                                       &len));
+            }
+
           if (eol_str)
             {
               /* Use the EOL as it was read from the patch file,
@@ -1447,9 +1448,8 @@ apply_hunk(patch_target_t *target, targe
               if (content_info->eol_style != svn_subst_eol_style_none)
                 eol_str = content_info->eol_str;
 
-              SVN_ERR(try_stream_write(content_info->patched,
-                                       target->patched_path, eol_str,
-                                       strlen(eol_str), iterpool));
+              len = strlen(eol_str);
+              SVN_ERR(svn_stream_write(content_info->patched, eol_str, &len));
             }
         }
     }
@@ -1619,31 +1619,30 @@ close_target_streams(const patch_target_
   apr_hash_index_t *hi;
   target_content_info_t *prop_content_info;
 
-   /* First the streams belonging to properties .. */
-      for (hi = apr_hash_first(pool, target->prop_targets);
-           hi;
-           hi = apr_hash_next(hi))
-        {
-          prop_patch_target_t *prop_target;
-          prop_target = svn__apr_hash_index_val(hi);
-          prop_content_info = prop_target->content_info;
-
-          /* ### If the prop did not exist pre-patching we'll not have a
-           * ### stream to read from. Find a better way to store info on
-           * ### the existence of the target prop. */
-          if (prop_content_info->stream)
-            SVN_ERR(svn_stream_close(prop_content_info->stream));
+  /* First the streams belonging to properties .. */
+  for (hi = apr_hash_first(pool, target->prop_targets);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      prop_patch_target_t *prop_target;
+      prop_target = svn__apr_hash_index_val(hi);
+      prop_content_info = prop_target->content_info;
 
-          SVN_ERR(svn_stream_close(prop_content_info->patched));
-        }
+      /* ### If the prop did not exist pre-patching we'll not have a
+       * ### stream to read from. Find a better way to store info on
+       * ### the existence of the target prop. */
+      if (prop_content_info->stream)
+        SVN_ERR(svn_stream_close(prop_content_info->stream));
 
+      SVN_ERR(svn_stream_close(prop_content_info->patched));
+    }
 
-   /* .. And then streams associted with the file. The reject stream is
-    * shared between all target_content_info structures. */
+  /* .. and then streams associated with the file.
+   * ### We're not closing the reject stream -- it still needed and
+   * ### will be closed later in write_out_rejected_hunks(). */
   if (target->kind_on_disk == svn_node_file)
     SVN_ERR(svn_stream_close(target->content_info->stream));
   SVN_ERR(svn_stream_close(target->content_info->patched));
-  SVN_ERR(svn_stream_close(target->content_info->reject));
 
   return SVN_NO_ERROR;
 }
@@ -1654,8 +1653,6 @@ close_target_streams(const patch_target_
  * in RESULT_POOL. Use WC_CTX as the working copy context.
  * STRIP_COUNT specifies the number of leading path components
  * which should be stripped from target paths in the patch.
- * OLD_PATCH_TARGET_NAMES indicates whether the old filename parsed
- * from the patch file should be preferred over the new filename.
  * REMOVE_TEMPFILES, PATCH_FUNC, and PATCH_BATON as in svn_client_patch().
  * IGNORE_WHITESPACE tells whether whitespace should be considered when
  * doing the matching.
@@ -1665,7 +1662,6 @@ static svn_error_t *
 apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch,
                 const char *abs_wc_path, svn_wc_context_t *wc_ctx,
                 int strip_count,
-                svn_boolean_t old_patch_target_names,
                 svn_boolean_t ignore_whitespace,
                 svn_boolean_t remove_tempfiles,
                 svn_client_patch_func_t patch_func,
@@ -1680,8 +1676,7 @@ apply_one_patch(patch_target_t **patch_t
   static const int MAX_FUZZ = 2;
   apr_hash_index_t *hash_index;
 
-  SVN_ERR(init_patch_target(&target, patch, abs_wc_path, wc_ctx,
-                            strip_count, old_patch_target_names,
+  SVN_ERR(init_patch_target(&target, patch, abs_wc_path, wc_ctx, strip_count,
                             remove_tempfiles, result_pool, scratch_pool));
   if (target->skipped)
     {
@@ -1744,7 +1739,7 @@ apply_one_patch(patch_target_t **patch_t
       if (hi->already_applied)
         continue;
       else if (hi->rejected)
-        SVN_ERR(reject_hunk(target, target->content_info, hi,
+        SVN_ERR(reject_hunk(target, target->content_info, hi->hunk,
                             NULL /* prop_name */, 
                             iterpool));
       else
@@ -1833,7 +1828,7 @@ apply_one_patch(patch_target_t **patch_t
           if (hi->already_applied)
             continue;
           else if (hi->rejected)
-            SVN_ERR(reject_hunk(target, prop_target->content_info, hi,
+            SVN_ERR(reject_hunk(target, prop_target->content_info, hi->hunk,
                                 prop_target->name,
                                 iterpool));
           else
@@ -2047,14 +2042,13 @@ create_missing_parents(patch_target_t *t
                * to version control. Allow cancellation since we
                * have not modified the working copy yet for this
                * target. */
-              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,
-                                  iterpool));
+
+              if (ctx->cancel_func)
+                SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+
+              SVN_ERR(svn_wc_add_from_disk(ctx->wc_ctx, local_abspath,
+                                           ctx->notify_func2, ctx->notify_baton2,
+                                           iterpool));
             }
         }
     }
@@ -2132,12 +2126,10 @@ install_patched_target(patch_target_t *t
               /* The target file didn't exist previously,
                * so add it to version control.
                * Suppress notification, we'll do that later (and also
-               * during dry-run). Also suppress cancellation because
+               * during dry-run). Don't allow cancellation because
                * we'd rather notify about what we did before aborting. */
-              SVN_ERR(svn_wc_add4(ctx->wc_ctx, target->local_abspath,
-                                  svn_depth_infinity,
-                                  NULL, SVN_INVALID_REVNUM,
-                                  NULL, NULL, NULL, NULL, pool));
+              SVN_ERR(svn_wc_add_from_disk(ctx->wc_ctx, target->local_abspath,
+                                           NULL, NULL, pool));
             }
 
           /* Restore the target's executable bit if necessary. */
@@ -2159,6 +2151,8 @@ write_out_rejected_hunks(patch_target_t 
                          svn_boolean_t dry_run,
                          apr_pool_t *pool)
 {
+  SVN_ERR(svn_stream_close(target->content_info->reject));
+
   if (! dry_run && (target->had_rejects || target->had_prop_rejects))
     {
       /* Write out rejected hunks, if any. */
@@ -2182,14 +2176,6 @@ install_patched_prop_targets(patch_targe
   apr_hash_index_t *hi;
   apr_pool_t *iterpool;
 
-  if (dry_run)
-    {
-      if (! target->has_text_changes && target->kind_on_disk == svn_node_none)
-        target->added = TRUE;
-
-      return SVN_NO_ERROR;
-    }
-
   iterpool = svn_pool_create(scratch_pool);
 
   for (hi = apr_hash_first(scratch_pool, target->prop_targets);
@@ -2201,19 +2187,22 @@ install_patched_prop_targets(patch_targe
       svn_stream_t *patched_stream;
       svn_stringbuf_t *line;
       svn_stringbuf_t *prop_content;
+      const svn_string_t *prop_val;
       const char *eol_str;
       svn_boolean_t eof;
+      svn_error_t *err;
 
       svn_pool_clear(iterpool);
 
       /* For a deleted prop we only set the value to NULL. */
       if (prop_target->operation == svn_diff_op_deleted)
         {
-          SVN_ERR(svn_wc_prop_set4(ctx->wc_ctx, target->local_abspath,
-                                   prop_target->name, NULL, 
-                                   TRUE /* skip_checks */,
-                                   NULL, NULL, /* suppress notification */
-                                   iterpool));
+          if (! dry_run)
+            SVN_ERR(svn_wc_prop_set4(ctx->wc_ctx, target->local_abspath,
+                                     prop_target->name, NULL, 
+                                     TRUE /* skip_checks */,
+                                     NULL, NULL, /* suppress notification */
+                                     iterpool));
           continue;
         }
 
@@ -2257,31 +2246,73 @@ install_patched_prop_targets(patch_targe
           && target->kind_on_disk == svn_node_none
           && ! target->added)
         {
-          SVN_ERR(svn_io_file_create(target->local_abspath, "", scratch_pool));
-          SVN_ERR(svn_wc_add4(ctx->wc_ctx, target->local_abspath,
-                              svn_depth_infinity,
-                              NULL, SVN_INVALID_REVNUM,
-                              ctx->cancel_func,
-                              ctx->cancel_baton,
-                              NULL, NULL, /* suppress notification */
-                              iterpool));
+          if (! dry_run)
+            {
+              SVN_ERR(svn_io_file_create(target->local_abspath, "",
+                                         scratch_pool));
+              if (ctx->cancel_func)
+                SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
+              SVN_ERR(svn_wc_add_from_disk(ctx->wc_ctx, target->local_abspath,
+                                           /* suppress notification */
+                                           NULL, NULL,
+                                           iterpool));
+            }
           target->added = TRUE;
         }
 
-      /* ### How should we handle SVN_ERR_ILLEGAL_TARGET and
-       * ### SVN_ERR_BAD_MIME_TYPE?
-       *
-       * ### stsp: I'd say reject the property hunk.
-       * ###       We should verify all modified prop hunk texts using
-       * ###       svn_wc_canonicalize_svn_prop() before starting the
-       * ###       patching process, to reject them as early as possible. */
-      SVN_ERR(svn_wc_prop_set4(ctx->wc_ctx, target->local_abspath,
-                               prop_target->name,
-                               svn_string_create_from_buf(prop_content, 
-                                                          iterpool),
-                               TRUE /* skip_checks */,
-                               NULL, NULL,
-                               iterpool));
+      /* Attempt to set the property, and reject all hunks if this fails. */
+      prop_val = svn_string_create_from_buf(prop_content, iterpool);
+      if (dry_run)
+        {
+          const svn_string_t *canon_propval;
+
+          err = svn_wc_canonicalize_svn_prop(&canon_propval,
+                                             prop_target->name,
+                                             prop_val, target->local_abspath,
+                                             target->db_kind,
+                                             TRUE, /* ### Skipping checks */
+                                             NULL, NULL,
+                                             iterpool);
+        }
+      else
+        {
+          err = (svn_wc_prop_set4(ctx->wc_ctx, target->local_abspath,
+                                  prop_target->name, prop_val,
+                                  TRUE, /* ### Skipping checks */
+                                  NULL, NULL,
+                                  iterpool));
+        }
+
+      if (err)
+        {
+          /* ### The errors which svn_wc_canonicalize_svn_prop() will
+           * ### return aren't documented. */
+          if (err->apr_err == SVN_ERR_ILLEGAL_TARGET ||
+              err->apr_err == SVN_ERR_NODE_UNEXPECTED_KIND ||
+              err->apr_err == SVN_ERR_IO_UNKNOWN_EOL ||
+              err->apr_err == SVN_ERR_BAD_MIME_TYPE ||
+              err->apr_err == SVN_ERR_CLIENT_INVALID_EXTERNALS_DESCRIPTION)
+            {
+              int i;
+
+              svn_error_clear(err);
+
+              for (i = 0; i < prop_target->content_info->hunks->nelts; i++)
+                {
+                  hunk_info_t *hunk_info;
+
+                  hunk_info = APR_ARRAY_IDX(prop_target->content_info->hunks,
+                                            i, hunk_info_t *);
+                  hunk_info->rejected = TRUE;
+                  SVN_ERR(reject_hunk(target, prop_target->content_info,
+                                      hunk_info->hunk, prop_target->name,
+                                      iterpool));
+                }
+            }
+          else
+            return svn_error_return(err);
+        }
+
     }
 
   svn_pool_destroy(iterpool);
@@ -2568,9 +2599,6 @@ typedef struct {
   /* Number of leading components to strip from patch target paths. */
   int strip_count;
 
-  /* Whether to use the old path from the patch file instead of the new one. */
-  svn_boolean_t old_patch_target_names;
-
   /* Whether to apply the patch in reverse. */
   svn_boolean_t reverse;
 
@@ -2636,7 +2664,6 @@ apply_patches(void *baton,
 
           SVN_ERR(apply_one_patch(&target, patch, btn->abs_wc_path,
                                   btn->ctx->wc_ctx, btn->strip_count,
-                                  btn->old_patch_target_names,
                                   btn->ignore_whitespace,
                                   btn->remove_tempfiles,
                                   btn->patch_func, btn->patch_baton,
@@ -2656,7 +2683,9 @@ apply_patches(void *baton,
 
               if (! target->skipped)
                 {
-                  if (target->has_text_changes || target->added)
+                  if (target->has_text_changes 
+                      || target->added 
+                      || target->deleted)
                     SVN_ERR(install_patched_target(target, btn->abs_wc_path,
                                                    btn->ctx, btn->dry_run,
                                                    iterpool));
@@ -2692,7 +2721,6 @@ svn_client_patch(const char *patch_abspa
                  const char *local_abspath,
                  svn_boolean_t dry_run,
                  int strip_count,
-                 svn_boolean_t old_patch_target_names,
                  svn_boolean_t reverse,
                  svn_boolean_t ignore_whitespace,
                  svn_boolean_t remove_tempfiles,
@@ -2713,7 +2741,6 @@ svn_client_patch(const char *patch_abspa
   baton.dry_run = dry_run;
   baton.ctx = ctx;
   baton.strip_count = strip_count;
-  baton.old_patch_target_names = old_patch_target_names;
   baton.reverse = reverse;
   baton.ignore_whitespace = ignore_whitespace;
   baton.remove_tempfiles = remove_tempfiles;

Modified: subversion/branches/py-tests-as-modules/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/py-tests-as-modules/subversion/libsvn_client/prop_commands.c?rev=1031230&r1=1031229&r2=1031230&view=diff
==============================================================================
--- subversion/branches/py-tests-as-modules/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/py-tests-as-modules/subversion/libsvn_client/prop_commands.c Thu Nov  4 20:48:21 2010
@@ -450,6 +450,53 @@ svn_client_propset4(const char *propname
     }
 }
 
+static svn_error_t *
+check_and_set_revprop(svn_revnum_t *set_rev,
+                      svn_ra_session_t *ra_session,
+                      const char *propname,
+                      const svn_string_t *original_propval,
+                      const svn_string_t *propval,
+                      apr_pool_t *pool)
+{
+  if (original_propval)
+    {
+      /* Ensure old value hasn't changed behind our back. */
+      svn_string_t *current;
+      SVN_ERR(svn_ra_rev_prop(ra_session, *set_rev, propname, &current, pool));
+
+      if (original_propval->data && (! current))
+        {
+          return svn_error_createf(
+                  SVN_ERR_RA_OUT_OF_DATE, NULL,
+                  _("revprop '%s' in r%ld is unexpectedly absent "
+                    "in repository (maybe someone else deleted it?)"),
+                  propname, *set_rev);
+        }
+      else if (original_propval->data
+               && (! svn_string_compare(original_propval, current)))
+        {
+          return svn_error_createf(
+                  SVN_ERR_RA_OUT_OF_DATE, NULL,
+                  _("revprop '%s' in r%ld has unexpected value "
+                    "in repository (maybe someone else changed it?)"),
+                  propname, *set_rev);
+        }
+      else if ((! original_propval->data) && current)
+        {
+          return svn_error_createf(
+                  SVN_ERR_RA_OUT_OF_DATE, NULL,
+                  _("revprop '%s' in r%ld is unexpectedly present "
+                    "in repository (maybe someone else set it?)"),
+                  propname, *set_rev);
+        }
+    }
+
+  SVN_ERR(svn_ra_change_rev_prop2(ra_session, *set_rev, propname, 
+                                  NULL, propval, pool));
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_client_revprop_set2(const char *propname,
                         const svn_string_t *propval,
@@ -462,6 +509,7 @@ svn_client_revprop_set2(const char *prop
                         apr_pool_t *pool)
 {
   svn_ra_session_t *ra_session;
+  svn_boolean_t be_atomic;
 
   if ((strcmp(propname, SVN_PROP_REVISION_AUTHOR) == 0)
       && propval
@@ -485,42 +533,31 @@ svn_client_revprop_set2(const char *prop
   SVN_ERR(svn_client__get_revision_number(set_rev, NULL, ctx->wc_ctx, NULL,
                                           ra_session, revision, pool));
 
-  if (original_propval)
-    {
-      /* Ensure old value hasn't changed behind our back. */
-      svn_string_t *current;
-      SVN_ERR(svn_ra_rev_prop(ra_session, *set_rev, propname, &current, pool));
+  SVN_ERR(svn_ra_has_capability(ra_session, &be_atomic,
+                                SVN_RA_CAPABILITY_ATOMIC_REVPROPS, pool));
+  if (be_atomic)
+    {
+      /* Convert ORIGINAL_PROPVAL to an OLD_VALUE_P. */
+      const svn_string_t *const *old_value_p;
+      const svn_string_t *unset = NULL;
+
+      if (original_propval == NULL)
+      	old_value_p = NULL;
+      else if (original_propval->data == NULL)
+      	old_value_p = &unset;
+      else
+      	old_value_p = &original_propval;
 
-      if (original_propval->data && (! current))
-        {
-          return svn_error_createf(
-                  SVN_ERR_RA_OUT_OF_DATE, NULL,
-                  _("revprop '%s' in r%ld is unexpectedly absent "
-                    "in repository (maybe someone else deleted it?)"),
-                  propname, *set_rev);
-        }
-      else if (original_propval->data
-               && (! svn_string_compare(original_propval, current)))
-        {
-          return svn_error_createf(
-                  SVN_ERR_RA_OUT_OF_DATE, NULL,
-                  _("revprop '%s' in r%ld has unexpected value "
-                    "in repository (maybe someone else changed it?)"),
-                  propname, *set_rev);
-        }
-      else if ((! original_propval->data) && current)
-        {
-          return svn_error_createf(
-                  SVN_ERR_RA_OUT_OF_DATE, NULL,
-                  _("revprop '%s' in r%ld is unexpectedly present "
-                    "in repository (maybe someone else set it?)"),
-                  propname, *set_rev);
-        }
+      /* The actual RA call. */
+      SVN_ERR(svn_ra_change_rev_prop2(ra_session, *set_rev, propname, 
+                                      old_value_p, propval, pool));
+    }
+  else
+    {
+      /* The actual RA call. */
+      SVN_ERR(check_and_set_revprop(set_rev, ra_session, propname,
+                                    original_propval, propval, pool));
     }
-
-  /* The actual RA call. */
-  SVN_ERR(svn_ra_change_rev_prop(ra_session, *set_rev, propname, propval,
-                                 pool));
 
   if (ctx->notify_func2)
     {