You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/12/02 21:55:18 UTC

svn commit: r1041580 [6/35] - in /subversion/branches/gpg-agent-password-store: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ contrib/hook-scripts/ contrib/server-side/ notes/http-and-webdav/ notes/wc-ng/ subversio...

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_client/patch.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_client/patch.c Thu Dec  2 20:55:08 2010
@@ -203,6 +203,9 @@ typedef struct patch_target_t {
   /* True if the patch changed any of the properties of the target. */
   svn_boolean_t has_prop_changes;
 
+  /* True if the patch contained a svn:special property. */
+  svn_boolean_t is_special;
+
   /* All the information that is specific to the content of the target. */
   target_content_info_t *content_info;
 
@@ -235,7 +238,7 @@ strip_path(const char **result, const ch
   apr_array_header_t *stripped;
 
   components = svn_path_decompose(path, scratch_pool);
-  if (strip_count >= components->nelts)
+  if (strip_count > components->nelts)
     return svn_error_createf(SVN_ERR_CLIENT_PATCH_BAD_STRIP_COUNT, NULL,
                              _("Cannot strip %u components from '%s'"),
                              strip_count,
@@ -346,9 +349,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 +499,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 +529,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 +574,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 +620,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)
@@ -913,9 +939,9 @@ match_hunk(svn_boolean_t *matched, targe
  * Return the line at which HUNK was matched in *MATCHED_LINE.
  * If the hunk did not match at all, set *MATCHED_LINE to zero.
  * If the hunk matched multiple times, and MATCH_FIRST is TRUE,
- * return the line number at which the first match occured in *MATCHED_LINE.
+ * return the line number at which the first match occurred in *MATCHED_LINE.
  * If the hunk matched multiple times, and MATCH_FIRST is FALSE,
- * return the line number at which the last match occured in *MATCHED_LINE.
+ * return the line number at which the last match occurred in *MATCHED_LINE.
  * If IGNORE_WHITESPACE is set, ignore whitespace during the matching.
  * If MATCH_MODIFIED is TRUE, match the modified hunk text,
  * rather than the original hunk text.
@@ -1270,12 +1296,13 @@ copy_lines_to_target(target_content_info
   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;
@@ -1286,7 +1313,7 @@ reject_hunk(patch_target_t *target, targ
     {
       const char *prop_header;
         
-      /* ### Print 'Added', 'Deleted' or 'Modified' instead of 'Propperty'.
+      /* ### Print 'Added', 'Deleted' or 'Modified' instead of 'Property'.
        */
       prop_header = apr_psprintf(pool, "Property: %s\n", prop_name);
       len = strlen(prop_header);
@@ -1296,18 +1323,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));
@@ -1320,7 +1347,7 @@ 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)
         {
@@ -1384,7 +1411,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;
         }
     }
@@ -1585,53 +1612,12 @@ send_patch_notification(const patch_targ
   return SVN_NO_ERROR;
 }
 
-/* Close the streams of the TARGET so that their content is flushed
- * to disk. This will also close underlying streams and files. Use POOL for
- * temporary allocations. */
-static svn_error_t *
-close_target_streams(const patch_target_t *target,
-                     apr_pool_t *pool)
-{
-  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));
-
-          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. */
-  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;
-}
-
 /* Apply a PATCH to a working copy at ABS_WC_PATH and put the result
  * into temporary files, to be installed in the working copy later.
  * Return information about the patch target in *PATCH_TARGET, allocated
  * 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.
@@ -1641,7 +1627,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,
@@ -1655,9 +1640,9 @@ apply_one_patch(patch_target_t **patch_t
   int i;
   static const int MAX_FUZZ = 2;
   apr_hash_index_t *hash_index;
+  target_content_info_t *prop_content_info;
 
-  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)
     {
@@ -1720,7 +1705,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
@@ -1754,6 +1739,9 @@ apply_one_patch(patch_target_t **patch_t
       prop_name = svn__apr_hash_index_key(hash_index);
       prop_patch = svn__apr_hash_index_val(hash_index);
 
+      if (! strcmp(prop_name, SVN_PROP_SPECIAL))
+        target->is_special = TRUE;
+
       /* We'll store matched hunks in prop_content_info. */
       prop_target = apr_hash_get(target->prop_targets, prop_name, 
                                  APR_HASH_KEY_STRING);
@@ -1809,7 +1797,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
@@ -1836,7 +1824,31 @@ apply_one_patch(patch_target_t **patch_t
 
   svn_pool_destroy(iterpool);
 
-  SVN_ERR(close_target_streams(target, scratch_pool));
+  /* Now close some streams that we don't need any longer to get
+   * file buffers flushed to disk. First, close the props streams... */
+  for (hash_index = apr_hash_first(scratch_pool, target->prop_targets);
+       hash_index;
+       hash_index = apr_hash_next(hash_index))
+    {
+      prop_patch_target_t *prop_target;
+      prop_target = svn__apr_hash_index_val(hash_index);
+      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));
+
+      SVN_ERR(svn_stream_close(prop_content_info->patched));
+    }
+
+  /* .. and then streams associated with the file.
+   * But 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));
 
   if (! target->skipped)
     {
@@ -2023,14 +2035,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));
             }
         }
     }
@@ -2100,20 +2111,42 @@ install_patched_target(patch_target_t *t
 
       if (! dry_run && ! target->skipped)
         {
-          /* Copy the patched file on top of the target file. */
-          SVN_ERR(svn_io_copy_file(target->patched_path,
-                                   target->local_abspath, FALSE, pool));
+          if (target->is_special)
+            {
+              svn_stream_t *stream;
+              svn_stream_t *patched_stream;
+              apr_file_t *file;
+
+              SVN_ERR(svn_io_file_open(&file, target->patched_path,
+                                       APR_READ | APR_BINARY, APR_OS_DEFAULT,
+                                       pool));
+
+              patched_stream = svn_stream_from_aprfile2(file, FALSE /* disown */,
+                                                pool);
+              SVN_ERR(svn_subst_create_specialfile(&stream, 
+                                                   target->local_abspath,
+                                                   pool, pool));
+              SVN_ERR(svn_stream_copy3(patched_stream, stream, 
+                                       NULL, /* cancel_func */ 
+                                       NULL, /* cancel_baton */
+                                       pool));
+            }
+          else
+            {
+              /* Copy the patched file on top of the target file. */
+              SVN_ERR(svn_io_copy_file(target->patched_path,
+                                       target->local_abspath, FALSE, pool));
+            }
+
           if (target->added || target->replaced)
             {
               /* 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. */
@@ -2135,6 +2168,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. */
@@ -2158,14 +2193,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);
@@ -2177,19 +2204,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;
         }
 
@@ -2233,31 +2263,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);
@@ -2544,9 +2616,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;
 
@@ -2612,7 +2681,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,
@@ -2670,7 +2738,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,
@@ -2686,12 +2753,15 @@ svn_client_patch(const char *patch_abspa
     return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
                             _("strip count must be positive"));
 
+  if (svn_path_is_url(local_abspath))
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a local path"), local_abspath);
+
   baton.patch_abspath = patch_abspath;
   baton.abs_wc_path = local_abspath;
   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/gpg-agent-password-store/subversion/libsvn_client/relocate.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_client/relocate.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_client/relocate.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_client/relocate.c Thu Dec  2 20:55:08 2010
@@ -125,15 +125,91 @@ validator_func(void *baton,
   return SVN_NO_ERROR;
 }
 
+
+/* Examing the array of svn_wc_external_item2_t's EXT_DESC (parsed
+   from the svn:externals property set on LOCAL_ABSPATH) and determine
+   if the external working copies described by such should be
+   relocated as a side-effect of the relocation of their parent
+   working copy (from OLD_PARENT_REPOS_ROOT_URL to
+   NEW_PARENT_REPOS_ROOT_URL).  If so, attempt said relocation.  */
+static svn_error_t *
+relocate_externals(const char *local_abspath,
+                   apr_array_header_t *ext_desc,
+                   const char *old_parent_repos_root_url,
+                   const char *new_parent_repos_root_url,
+                   svn_client_ctx_t *ctx,
+                   apr_pool_t *scratch_pool)
+{
+  const char *url;
+  apr_pool_t *iterpool;
+  int i;
+
+  SVN_ERR(svn_client_url_from_path2(&url, local_abspath, ctx,
+                                    scratch_pool, scratch_pool));
+
+  /* Parse an externals definition into an array of external items. */
+
+  iterpool = svn_pool_create(scratch_pool);
+
+  for (i = 0; i < ext_desc->nelts; i++)
+    {
+      svn_wc_external_item2_t *ext_item =
+        APR_ARRAY_IDX(ext_desc, i, svn_wc_external_item2_t *);
+      const char *target_repos_root_url;
+      const char *target_abspath;
+      
+      svn_pool_clear(iterpool);
+
+      /* If this external isn't pulled in via a relative URL, ignore
+         it.  There's no sense in relocating a working copy only to
+         have the next 'svn update' try to point it back to another
+         location. */
+      if (! ((strncmp("../", ext_item->url, 3) == 0) ||
+             (strncmp("^/", ext_item->url, 2) == 0)))
+        continue;
+
+      /* If the external working copy's not-yet-relocated repos root
+         URL matches the primary working copy's pre-relocated
+         repository root URL, try to relocate that external, too.
+         You might wonder why this check is needed, given that we're
+         already limiting ourselves to externals pulled via URLs
+         relative to their primary working copy.  Well, it's because
+         you can use "../" to "crawl up" above one repository's URL
+         space and down into another one.  */
+      SVN_ERR(svn_dirent_get_absolute(&target_abspath,
+                                      svn_dirent_join(local_abspath,
+                                                      ext_item->target_dir,
+                                                      iterpool),
+                                      iterpool));
+      SVN_ERR(svn_client_root_url_from_path(&target_repos_root_url,
+                                            target_abspath, ctx, iterpool));
+
+      if (strcmp(target_repos_root_url, old_parent_repos_root_url) == 0)
+        SVN_ERR(svn_client_relocate2(target_abspath,
+                                     old_parent_repos_root_url,
+                                     new_parent_repos_root_url,
+                                     TRUE, ctx, iterpool));
+    }
+
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
 svn_error_t *
 svn_client_relocate2(const char *wcroot_dir,
-                     const char *from,
-                     const char *to,
+                     const char *from_prefix,
+                     const char *to_prefix,
+                     svn_boolean_t ignore_externals,
                      svn_client_ctx_t *ctx,
                      apr_pool_t *pool)
 {
   struct validator_baton_t vb;
   const char *local_abspath;
+  apr_hash_t *externals_hash = NULL;
+  apr_hash_index_t *hi;
+  apr_pool_t *iterpool = NULL;
+  const char *old_repos_root_url, *new_repos_root_url;
 
   /* Populate our validator callback baton, and call the relocate code. */
   vb.ctx = ctx;
@@ -141,9 +217,61 @@ svn_client_relocate2(const char *wcroot_
   vb.url_uuids = apr_array_make(pool, 1, sizeof(struct url_uuid_t));
   vb.pool = pool;
 
+  if (svn_path_is_url(wcroot_dir))
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a local path"),
+                             wcroot_dir);
+
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, wcroot_dir, pool));
-  SVN_ERR(svn_wc_relocate4(ctx->wc_ctx, local_abspath, from, to,
+
+  /* If we're ignoring externals, just relocate and get outta here. */
+  if (ignore_externals)
+    {
+      return svn_error_return(svn_wc_relocate4(ctx->wc_ctx, local_abspath,
+                                               from_prefix, to_prefix,
+                                               validator_func, &vb, pool));
+    }
+
+  /* Fetch our current root URL. */
+  SVN_ERR(svn_client_root_url_from_path(&old_repos_root_url, local_abspath,
+                                        ctx, pool));
+
+  /* Perform the relocation. */
+  SVN_ERR(svn_wc_relocate4(ctx->wc_ctx, local_abspath, from_prefix, to_prefix,
                            validator_func, &vb, pool));
 
+  /* Now fetch new current root URL. */
+  SVN_ERR(svn_client_root_url_from_path(&new_repos_root_url, local_abspath,
+                                        ctx, pool));
+
+
+  /* Relocate externals, too (if any). */
+  SVN_ERR(svn_client__crawl_for_externals(&externals_hash, local_abspath,
+                                          svn_depth_infinity, ctx, pool, pool));
+  if (! apr_hash_count(externals_hash))
+    return SVN_NO_ERROR;
+
+  iterpool = svn_pool_create(pool);
+
+  for (hi = apr_hash_first(pool, externals_hash);
+       hi != NULL;
+       hi = apr_hash_next(hi))
+    {
+      const char *this_abspath = svn__apr_hash_index_key(hi);
+      const svn_string_t *pval = svn__apr_hash_index_val(hi);
+      apr_array_header_t *ext_desc;
+
+      svn_pool_clear(iterpool);
+
+      SVN_ERR(svn_wc_parse_externals_description3(&ext_desc, this_abspath,
+                                                  pval->data, FALSE,
+                                                  iterpool));
+      if (ext_desc->nelts)
+        SVN_ERR(relocate_externals(this_abspath, ext_desc, old_repos_root_url,
+                                   new_repos_root_url, ctx, iterpool));
+    }
+    
+  svn_pool_destroy(iterpool);
+
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_client/resolved.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_client/resolved.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_client/resolved.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_client/resolved.c Thu Dec  2 20:55:08 2010
@@ -36,6 +36,7 @@
 #include "client.h"
 #include "private/svn_wc_private.h"
 
+#include "svn_private_config.h"
 
 /*** Code. ***/
 
@@ -48,6 +49,10 @@ svn_client_resolve(const char *path,
 {
   const char *local_abspath;
 
+  if (svn_path_is_url(path))
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a local path"), path);
+
   SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
 
   SVN_ERR(svn_wc_resolved_conflict5(ctx->wc_ctx, local_abspath,

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_client/revert.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_client/revert.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_client/revert.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_client/revert.c Thu Dec  2 20:55:08 2010
@@ -27,6 +27,7 @@
 
 /*** Includes. ***/
 
+#include "svn_path.h"
 #include "svn_wc.h"
 #include "svn_client.h"
 #include "svn_dirent_uri.h"
@@ -37,6 +38,7 @@
 #include "client.h"
 #include "private/svn_wc_private.h"
 
+#include "svn_private_config.h"
 
 
 /*** Code. ***/
@@ -121,6 +123,17 @@ svn_client_revert2(const apr_array_heade
   svn_boolean_t use_commit_times;
   struct revert_with_write_lock_baton baton;
 
+  /* Don't even attempt to modify the working copy if any of the
+   * targets look like URLs. URLs are invalid input. */
+  for (i = 0; i < paths->nelts; i++)
+    {
+      const char *path = APR_ARRAY_IDX(paths, i, const char *);
+
+      if (svn_path_is_url(path))
+        return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                                 _("'%s' is not a local path"), path);
+    }
+  
   cfg = ctx->config ? apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
                                    APR_HASH_KEY_STRING) : NULL;
 

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_client/status.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_client/status.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_client/status.c Thu Dec  2 20:55:08 2010
@@ -32,6 +32,7 @@
 #include "svn_pools.h"
 #include "client.h"
 
+#include "svn_path.h"
 #include "svn_dirent_uri.h"
 #include "svn_delta.h"
 #include "svn_client.h"
@@ -266,7 +267,11 @@ svn_client_status5(svn_revnum_t *result_
   apr_array_header_t *ignores;
   svn_error_t *err;
   apr_hash_t *changelist_hash = NULL;
-  struct svn_cl__externals_store externals_store = { NULL };
+  struct svn_client__external_func_baton_t externals_store = { NULL };
+
+  if (svn_path_is_url(path))
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a local path"), path);
 
   if (changelists && changelists->nelts)
     SVN_ERR(svn_hash_from_cstring_keys(&changelist_hash, changelists, pool));
@@ -351,7 +356,7 @@ svn_client_status5(svn_revnum_t *result_
 
   if (!ignore_externals)
     {
-      externals_store.pool = pool;
+      externals_store.result_pool = pool;
       externals_store.externals_new = apr_hash_make(pool);
     }
 
@@ -387,10 +392,10 @@ svn_client_status5(svn_revnum_t *result_
                                     dir_abspath, target_basename,
                                     depth, get_all,
                                     no_ignore, ignores, tweak_status, &sb,
-                                    ignore_externals ? NULL
-                                                     : svn_cl__store_externals,
-                                    ignore_externals ? NULL
-                                                     : &externals_store,
+                                    ignore_externals
+                                        ? NULL
+                                        : svn_client__external_info_gatherer,
+                                    ignore_externals ? NULL : &externals_store,
                                     ctx->cancel_func, ctx->cancel_baton,
                                     pool, pool));
 
@@ -511,10 +516,10 @@ svn_client_status5(svn_revnum_t *result_
       err = svn_wc_walk_status(ctx->wc_ctx, target_abspath,
                                depth, get_all, no_ignore, ignores,
                                tweak_status, &sb,
-                               ignore_externals ? NULL
-                                                : svn_cl__store_externals,
-                               ignore_externals ? NULL
-                                                : &externals_store,
+                               ignore_externals
+                                   ? NULL
+                                   : svn_client__external_info_gatherer,
+                               ignore_externals ? NULL : &externals_store,
                                ctx->cancel_func, ctx->cancel_baton,
                                pool);
 

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_client/switch.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_client/switch.c Thu Dec  2 20:55:08 2010
@@ -329,6 +329,11 @@ svn_client_switch2(svn_revnum_t *result_
                    svn_client_ctx_t *ctx,
                    apr_pool_t *pool)
 {
+  if (svn_path_is_url(path))
+    return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
+                             _("'%s' is not a local path"),
+                             path);
+
   return svn_client__switch_internal(result_rev, path, switch_url,
                                      peg_revision, revision, depth,
                                      depth_is_sticky, NULL, ignore_externals,

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_client/update.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_client/update.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_client/update.c Thu Dec  2 20:55:08 2010
@@ -44,7 +44,18 @@
 
 /*** Code. ***/
 
-
+/* This is a helper for svn_client__update_internal(), which see for
+   an explanation of most of these parameters.  Some stuff that's
+   unique is as follows:
+
+   ANCHOR_ABSPATH is the local absolute path of the update anchor.
+   This is typically either the same as LOCAL_ABSPATH, or the
+   immediate parent of LOCAL_ABSPATH.
+
+   If NOTIFY_SUMMARY is set (and there's a notification hander in
+   CTX), transmit the final update summary upon successful
+   completion of the update.
+*/
 static svn_error_t *
 update_internal(svn_revnum_t *result_rev,
                 const char *local_abspath,
@@ -56,6 +67,7 @@ update_internal(svn_revnum_t *result_rev
                 svn_boolean_t allow_unver_obstructions,
                 svn_boolean_t *timestamp_sleep,
                 svn_boolean_t innerupdate,
+                svn_boolean_t notify_summary,
                 svn_client_ctx_t *ctx,
                 apr_pool_t *pool)
 {
@@ -144,6 +156,20 @@ update_internal(svn_revnum_t *result_rev
     ? svn_cstring_split(preserved_exts_str, "\n\r\t\v ", FALSE, pool)
     : NULL;
 
+  /* Let everyone know we're starting a real update (unless we're
+     asked not to). */
+  if (ctx->notify_func2 && notify_summary)
+    {
+      svn_wc_notify_t *notify
+        = svn_wc_create_notify(local_abspath, svn_wc_notify_update_started,
+                               pool);
+      notify->kind = svn_node_none;
+      notify->content_state = notify->prop_state
+        = svn_wc_notify_state_inapplicable;
+      notify->lock_state = svn_wc_notify_lock_state_inapplicable;
+      (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
+    }
+
   /* Open an RA session for the URL */
   SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url,
                                                anchor_url,
@@ -235,8 +261,8 @@ update_internal(svn_revnum_t *result_rev
   if (sleep_here)
     svn_io_sleep_for_timestamps(local_abspath, pool);
 
-  /* Let everyone know we're finished here. */
-  if (ctx->notify_func2)
+  /* Let everyone know we're finished here (unless we're asked not to). */
+  if (ctx->notify_func2 && notify_summary)
     {
       svn_wc_notify_t *notify
         = svn_wc_create_notify(local_abspath, svn_wc_notify_update_completed,
@@ -266,44 +292,99 @@ svn_client__update_internal(svn_revnum_t
                             svn_boolean_t allow_unver_obstructions,
                             svn_boolean_t *timestamp_sleep,
                             svn_boolean_t innerupdate,
+                            svn_boolean_t make_parents,
                             svn_client_ctx_t *ctx,
                             apr_pool_t *pool)
 {
-  const char *anchor_abspath;
+  const char *anchor_abspath, *lockroot_abspath;
   svn_error_t *err;
+  svn_opt_revision_t peg_revision = *((svn_opt_revision_t *)revision);
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
+  SVN_ERR_ASSERT(! (innerupdate && make_parents));
+
+  if (make_parents)
+    {
+      int i;
+      const char *parent_abspath = local_abspath;
+      apr_array_header_t *missing_parents = 
+        apr_array_make(pool, 4, sizeof(const char *));
+
+      while (1)
+        {
+          /* Try to lock.  If we can't lock because our target (or its
+             parent) isn't a working copy, we'll try to walk up the
+             tree to find a working copy, remembering this path's
+             parent as one we need to flesh out.  */
+          err = svn_wc__acquire_write_lock(&lockroot_abspath, ctx->wc_ctx,
+                                           parent_abspath, !innerupdate,
+                                           pool, pool);
+          if (!err)
+            break;
+          if ((err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
+              || svn_dirent_is_root(parent_abspath, strlen(parent_abspath)))
+            return err;
+          svn_error_clear(err);
+
+          /* Remember the parent of our update target as a missing
+             parent. */
+          parent_abspath = svn_dirent_dirname(parent_abspath, pool);
+          APR_ARRAY_PUSH(missing_parents, const char *) = parent_abspath;
+        }
+
+      /* Run 'svn up --depth=empty' (effectively) on the missing
+         parents, if any. */
+      anchor_abspath = lockroot_abspath;
+      for (i = missing_parents->nelts - 1; i >= 0; i--)
+        {
+          const char *missing_parent =
+            APR_ARRAY_IDX(missing_parents, i, const char *);
+          err = update_internal(result_rev, missing_parent, anchor_abspath,
+                                &peg_revision, svn_depth_empty, FALSE,
+                                ignore_externals, allow_unver_obstructions,
+                                timestamp_sleep, innerupdate, FALSE,
+                                ctx, pool);
+          if (err)
+            goto cleanup;
+          anchor_abspath = missing_parent;
 
-  if (!innerupdate)
-    SVN_ERR(svn_wc__acquire_write_lock(&anchor_abspath,
-                                       ctx->wc_ctx, local_abspath, TRUE,
-                                       pool, pool));
+          /* If we successfully updated a missing parent, let's re-use
+             the returned revision number for future updates for the
+             sake of consistency. */
+          peg_revision.kind = svn_opt_revision_number;
+          peg_revision.value.number = *result_rev;
+        }
+    }
   else
-    SVN_ERR(svn_wc__acquire_write_lock(&anchor_abspath,
-                                       ctx->wc_ctx, local_abspath, FALSE,
-                                       pool, pool));
+    {
+      SVN_ERR(svn_wc__acquire_write_lock(&lockroot_abspath, ctx->wc_ctx,
+                                         local_abspath, !innerupdate,
+                                         pool, pool));
+      anchor_abspath = lockroot_abspath;
+    }
 
   err = update_internal(result_rev, local_abspath, anchor_abspath,
-                         revision, depth, depth_is_sticky,
-                         ignore_externals, allow_unver_obstructions,
-                         timestamp_sleep, innerupdate, ctx, pool);
-
+                        &peg_revision, depth, depth_is_sticky,
+                        ignore_externals, allow_unver_obstructions,
+                        timestamp_sleep, innerupdate, TRUE, ctx, pool);
+ cleanup:
   err = svn_error_compose_create(
             err,
-            svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool));
+            svn_wc__release_write_lock(ctx->wc_ctx, lockroot_abspath, pool));
 
   return svn_error_return(err);
 }
 
 
 svn_error_t *
-svn_client_update3(apr_array_header_t **result_revs,
+svn_client_update4(apr_array_header_t **result_revs,
                    const apr_array_header_t *paths,
                    const svn_opt_revision_t *revision,
                    svn_depth_t depth,
                    svn_boolean_t depth_is_sticky,
                    svn_boolean_t ignore_externals,
                    svn_boolean_t allow_unver_obstructions,
+                   svn_boolean_t make_parents,
                    svn_client_ctx_t *ctx,
                    apr_pool_t *pool)
 {
@@ -340,7 +421,8 @@ svn_client_update3(apr_array_header_t **
                                             revision, depth, depth_is_sticky,
                                             ignore_externals,
                                             allow_unver_obstructions,
-                                            &sleep, FALSE, ctx, subpool);
+                                            &sleep, FALSE, make_parents,
+                                            ctx, subpool);
 
           if (err && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
             {

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_delta/path_driver.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_delta/path_driver.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_delta/path_driver.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_delta/path_driver.c Thu Dec  2 20:55:08 2010
@@ -194,7 +194,9 @@ svn_delta_path_driver(const svn_delta_ed
            current one.  For the first iteration, this is just the
            empty string. ***/
       if (i > 0)
-        common = svn_relpath_get_longest_ancestor(last_path, path, iterpool);
+        common = (last_path[0] == '/')
+          ? svn_fspath__get_longest_ancestor(last_path, path, iterpool)
+          : svn_relpath_get_longest_ancestor(last_path, path, iterpool);
       common_len = strlen(common);
 
       /*** Step B - Close any directories between the last path and
@@ -215,7 +217,7 @@ svn_delta_path_driver(const svn_delta_ed
       /*** Step C - Open any directories between the common ancestor
            and the parent of the current path. ***/
       if (*path == '/')
-        svn_uri_split(&pdir, &bname, path, iterpool);
+        svn_fspath__split(&pdir, &bname, path, iterpool);
       else
         svn_relpath_split(&pdir, &bname, path, iterpool);
       if (strlen(pdir) > common_len)

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_diff/diff_file.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_diff/diff_file.c Thu Dec  2 20:55:08 2010
@@ -67,21 +67,26 @@ typedef struct svn_diff__file_token_t
 typedef struct svn_diff__file_baton_t
 {
   const svn_diff_file_options_t *options;
-  const char *path[4];
 
-  apr_file_t *file[4];
-  apr_off_t size[4];
+  struct file_info {
+    const char *path;  /* path to this file, absolute or relative to CWD */
 
-  int chunk[4];
-  char *buffer[4];
-  char *curp[4];
-  char *endp[4];
+    /* All the following fields are active while this datasource is open */
+    apr_file_t *file;  /* handle of this file */
+    apr_off_t size;    /* total raw size in bytes of this file */
+
+    /* The current chunk: CHUNK_SIZE bytes except for the last chunk. */
+    int chunk;     /* the current chunk number, zero-based */
+    char *buffer;  /* a buffer containing the current chunk */
+    char *curp;    /* current position in the current chunk */
+    char *endp;    /* next memory address after the current chunk */
+
+    svn_diff__normalize_state_t normalize_state;
+  } files[4];
 
   /* List of free tokens that may be reused. */
   svn_diff__file_token_t *tokens;
 
-  svn_diff__normalize_state_t normalize_state[4];
-
   apr_pool_t *pool;
 } svn_diff__file_baton_t;
 
@@ -198,26 +203,30 @@ map_or_read_file(apr_file_t **file,
 }
 
 
-/* Implements svn_diff_fns_t::datasource_open */
+/* Let FILE stand for the file_info struct element of BATON->files that is
+ * indexed by DATASOURCE.  BATON's type is (svn_diff__file_baton_t *).
+ *
+ * Open the file at FILE.path; initialize FILE.file, FILE.size, FILE.buffer,
+ * FILE.curp and FILE.endp; allocate a buffer and read the first chunk.
+ *
+ * Implements svn_diff_fns_t::datasource_open. */
 static svn_error_t *
 datasource_open(void *baton, svn_diff_datasource_e datasource)
 {
   svn_diff__file_baton_t *file_baton = baton;
-  int idx;
+  struct file_info *file = &file_baton->files[datasource_to_index(datasource)];
   apr_finfo_t finfo;
   apr_off_t length;
   char *curp;
   char *endp;
 
-  idx = datasource_to_index(datasource);
-
-  SVN_ERR(svn_io_file_open(&file_baton->file[idx], file_baton->path[idx],
+  SVN_ERR(svn_io_file_open(&file->file, file->path,
                            APR_READ, APR_OS_DEFAULT, file_baton->pool));
 
   SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE,
-                               file_baton->file[idx], file_baton->pool));
+                               file->file, file_baton->pool));
 
-  file_baton->size[idx] = finfo.size;
+  file->size = finfo.size;
   length = finfo.size > CHUNK_SIZE ? CHUNK_SIZE : finfo.size;
 
   if (length == 0)
@@ -226,10 +235,10 @@ datasource_open(void *baton, svn_diff_da
   endp = curp = apr_palloc(file_baton->pool, (apr_size_t) length);
   endp += length;
 
-  file_baton->buffer[idx] = file_baton->curp[idx] = curp;
-  file_baton->endp[idx] = endp;
+  file->buffer = file->curp = curp;
+  file->endp = endp;
 
-  return read_chunk(file_baton->file[idx], file_baton->path[idx],
+  return read_chunk(file->file, file->path,
                     curp, length, 0, file_baton->pool);
 }
 
@@ -252,7 +261,7 @@ datasource_get_next_token(apr_uint32_t *
 {
   svn_diff__file_baton_t *file_baton = baton;
   svn_diff__file_token_t *file_token;
-  int idx;
+  struct file_info *file = &file_baton->files[datasource_to_index(datasource)];
   char *endp;
   char *curp;
   char *eol;
@@ -264,15 +273,13 @@ datasource_get_next_token(apr_uint32_t *
 
   *token = NULL;
 
-  idx = datasource_to_index(datasource);
+  curp = file->curp;
+  endp = file->endp;
 
-  curp = file_baton->curp[idx];
-  endp = file_baton->endp[idx];
-
-  last_chunk = offset_to_chunk(file_baton->size[idx]);
+  last_chunk = offset_to_chunk(file->size);
 
   if (curp == endp
-      && last_chunk == file_baton->chunk[idx])
+      && last_chunk == file->chunk)
     {
       return SVN_NO_ERROR;
     }
@@ -289,8 +296,8 @@ datasource_get_next_token(apr_uint32_t *
     }
 
   file_token->datasource = datasource;
-  file_token->offset = chunk_to_offset(file_baton->chunk[idx])
-                       + (curp - file_baton->buffer[idx]);
+  file_token->offset = chunk_to_offset(file->chunk)
+                       + (curp - file->buffer);
   file_token->raw_length = 0;
   file_token->length = 0;
 
@@ -311,7 +318,7 @@ datasource_get_next_token(apr_uint32_t *
             }
         }
 
-      if (file_baton->chunk[idx] == last_chunk)
+      if (file->chunk == last_chunk)
         {
           eol = endp;
           break;
@@ -320,21 +327,21 @@ datasource_get_next_token(apr_uint32_t *
       length = endp - curp;
       file_token->raw_length += length;
       svn_diff__normalize_buffer(&curp, &length,
-                                 &file_baton->normalize_state[idx],
+                                 &file->normalize_state,
                                  curp, file_baton->options);
       file_token->length += length;
       h = svn_diff__adler32(h, curp, length);
 
-      curp = endp = file_baton->buffer[idx];
-      file_baton->chunk[idx]++;
-      length = file_baton->chunk[idx] == last_chunk ?
-        offset_in_chunk(file_baton->size[idx]) : CHUNK_SIZE;
+      curp = endp = file->buffer;
+      file->chunk++;
+      length = file->chunk == last_chunk ?
+        offset_in_chunk(file->size) : CHUNK_SIZE;
       endp += length;
-      file_baton->endp[idx] = endp;
+      file->endp = endp;
 
-      SVN_ERR(read_chunk(file_baton->file[idx], file_baton->path[idx],
+      SVN_ERR(read_chunk(file->file, file->path,
                          curp, length,
-                         chunk_to_offset(file_baton->chunk[idx]),
+                         chunk_to_offset(file->chunk),
                          file_baton->pool));
 
       /* If the last chunk ended in a CR, we're done. */
@@ -349,7 +356,7 @@ datasource_get_next_token(apr_uint32_t *
 
   length = eol - curp;
   file_token->raw_length += length;
-  file_baton->curp[idx] = eol;
+  file->curp = eol;
 
   /* If the file length is exactly a multiple of CHUNK_SIZE, we will end up
    * with a spurious empty token.  Avoid returning it.
@@ -360,7 +367,7 @@ datasource_get_next_token(apr_uint32_t *
     {
       char *c = curp;
       svn_diff__normalize_buffer(&c, &length,
-                                 &file_baton->normalize_state[idx],
+                                 &file->normalize_state,
                                  curp, file_baton->options);
 
       file_token->norm_offset = file_token->offset;
@@ -388,13 +395,12 @@ token_compare(void *baton, void *token1,
   char buffer[2][COMPARE_CHUNK_SIZE];
   char *bufp[2];
   apr_off_t offset[2];
-  int idx[2];
+  struct file_info *file[2];
   apr_off_t length[2];
   apr_off_t total_length;
   /* How much is left to read of each token from the file. */
   apr_off_t raw_length[2];
   int i;
-  int chunk[2];
   svn_diff__normalize_state_t state[2];
 
   file_token[0] = token1;
@@ -420,17 +426,18 @@ token_compare(void *baton, void *token1,
 
   for (i = 0; i < 2; ++i)
     {
-      idx[i] = datasource_to_index(file_token[i]->datasource);
+      int idx = datasource_to_index(file_token[i]->datasource);
+
+      file[i] = &file_baton->files[idx];
       offset[i] = file_token[i]->norm_offset;
-      chunk[i] = file_baton->chunk[idx[i]];
       state[i] = svn_diff__normalize_state_normal;
 
-      if (offset_to_chunk(offset[i]) == chunk[i])
+      if (offset_to_chunk(offset[i]) == file[i]->chunk)
         {
           /* If the start of the token is in memory, the entire token is
            * in memory.
            */
-          bufp[i] = file_baton->buffer[idx[i]];
+          bufp[i] = file[i]->buffer;
           bufp[i] += offset_in_chunk(offset[i]);
 
           length[i] = total_length;
@@ -458,15 +465,15 @@ token_compare(void *baton, void *token1,
                                          NULL,
                                          _("The file '%s' changed unexpectedly"
                                            " during diff"),
-                                         file_baton->path[idx[i]]);
+                                         file[i]->path);
 
               /* Read a chunk from disk into a buffer */
               bufp[i] = buffer[i];
               length[i] = raw_length[i] > COMPARE_CHUNK_SIZE ?
                 COMPARE_CHUNK_SIZE : raw_length[i];
 
-              SVN_ERR(read_chunk(file_baton->file[idx[i]],
-                                 file_baton->path[idx[i]],
+              SVN_ERR(read_chunk(file[i]->file,
+                                 file[i]->path,
                                  bufp[i], length[i], offset[i],
                                  file_baton->pool));
               offset[i] += length[i];
@@ -555,12 +562,42 @@ svn_diff_file_options_create(apr_pool_t 
   return apr_pcalloc(pool, sizeof(svn_diff_file_options_t));
 }
 
+/* A baton for use with opt_parsing_error_func(). */
+struct opt_parsing_error_baton_t
+{
+  svn_error_t *err;
+  apr_pool_t *pool;
+};
+
+/* Store an error message from apr_getopt_long().  Set BATON->err to a new
+ * error with a message generated from FMT and the remaining arguments.
+ * Implements apr_getopt_err_fn_t. */
+static void
+opt_parsing_error_func(void *baton,
+                       const char *fmt, ...)
+{
+  struct opt_parsing_error_baton_t *b = baton;
+  const char *message;
+  va_list ap;
+
+  va_start(ap, fmt);
+  message = apr_pvsprintf(b->pool, fmt, ap);
+  va_end(ap);
+
+  /* Skip leading ": " (if present, which it always is in known cases). */
+  if (strncmp(message, ": ", 2) == 0)
+    message += 2;
+
+  b->err = svn_error_create(SVN_ERR_INVALID_DIFF_OPTION, NULL, message);
+}
+
 svn_error_t *
 svn_diff_file_options_parse(svn_diff_file_options_t *options,
                             const apr_array_header_t *args,
                             apr_pool_t *pool)
 {
   apr_getopt_t *os;
+  struct opt_parsing_error_baton_t opt_parsing_error_baton = { NULL, pool };
   /* Make room for each option (starting at index 1) plus trailing NULL. */
   const char **argv = apr_palloc(pool, sizeof(char*) * (args->nelts + 2));
 
@@ -569,8 +606,12 @@ svn_diff_file_options_parse(svn_diff_fil
   argv[args->nelts + 1] = NULL;
 
   apr_getopt_init(&os, pool, args->nelts + 1, argv);
-  /* No printing of error messages, please! */
-  os->errfn = NULL;
+
+  /* Capture any error message from apr_getopt_long().  This will typically
+   * say which option is wrong, which we would not otherwise know. */
+  os->errfn = opt_parsing_error_func;
+  os->errarg = &opt_parsing_error_baton;
+
   while (1)
     {
       const char *opt_arg;
@@ -580,7 +621,13 @@ svn_diff_file_options_parse(svn_diff_fil
       if (APR_STATUS_IS_EOF(err))
         break;
       if (err)
-        return svn_error_wrap_apr(err, _("Error parsing diff options"));
+        /* Wrap apr_getopt_long()'s error message.  Its doc string implies
+         * it always will produce one, but never mind if it doesn't.  Avoid
+         * using the message associated with the return code ERR, because
+         * it refers to the "command line" which may be misleading here. */
+        return svn_error_create(SVN_ERR_INVALID_DIFF_OPTION,
+                                opt_parsing_error_baton.err,
+                                _("Error in options to internal diff"));
 
       switch (opt_id)
         {
@@ -623,8 +670,8 @@ svn_diff_file_diff_2(svn_diff_t **diff,
 
   memset(&baton, 0, sizeof(baton));
   baton.options = options;
-  baton.path[0] = original;
-  baton.path[1] = modified;
+  baton.files[0].path = original;
+  baton.files[1].path = modified;
   baton.pool = svn_pool_create(pool);
 
   SVN_ERR(svn_diff_diff(diff, &baton, &svn_diff__file_vtable, pool));
@@ -645,9 +692,9 @@ svn_diff_file_diff3_2(svn_diff_t **diff,
 
   memset(&baton, 0, sizeof(baton));
   baton.options = options;
-  baton.path[0] = original;
-  baton.path[1] = modified;
-  baton.path[2] = latest;
+  baton.files[0].path = original;
+  baton.files[1].path = modified;
+  baton.files[2].path = latest;
   baton.pool = svn_pool_create(pool);
 
   SVN_ERR(svn_diff_diff3(diff, &baton, &svn_diff__file_vtable, pool));
@@ -669,10 +716,10 @@ svn_diff_file_diff4_2(svn_diff_t **diff,
 
   memset(&baton, 0, sizeof(baton));
   baton.options = options;
-  baton.path[0] = original;
-  baton.path[1] = modified;
-  baton.path[2] = latest;
-  baton.path[3] = ancestor;
+  baton.files[0].path = original;
+  baton.files[1].path = modified;
+  baton.files[2].path = latest;
+  baton.files[3].path = ancestor;
   baton.pool = svn_pool_create(pool);
 
   SVN_ERR(svn_diff_diff4(diff, &baton, &svn_diff__file_vtable, pool));

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_diff/parse-diff.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_diff/parse-diff.c Thu Dec  2 20:55:08 2010
@@ -28,6 +28,7 @@
 #include "svn_error.h"
 #include "svn_io.h"
 #include "svn_pools.h"
+#include "svn_props.h"
 #include "svn_string.h"
 #include "svn_utf.h"
 #include "svn_dirent_uri.h"
@@ -189,6 +190,7 @@ parse_hunk_header(const char *header, sv
                   const char *atat, apr_pool_t *pool)
 {
   const char *p;
+  const char *start;
   svn_stringbuf_t *range;
 
   p = header + strlen(atat);
@@ -201,16 +203,18 @@ parse_hunk_header(const char *header, sv
     return FALSE;
   /* OK, this may be worth allocating some memory for... */
   range = svn_stringbuf_create_ensure(31, pool);
-  p++;
+  start = ++p;
   while (*p && *p != ' ')
     {
-      svn_stringbuf_appendbyte(range, *p);
       p++;
     }
+
   if (*p != ' ')
     /* No no no... */
     return FALSE;
 
+  svn_stringbuf_appendbytes(range, start, p - start);
+
   /* Try to parse the first range. */
   if (! parse_range(&hunk->original_start, &hunk->original_length, range->data))
     return FALSE;
@@ -222,16 +226,17 @@ parse_hunk_header(const char *header, sv
     /* Eeek! */
     return FALSE;
   /* OK, this may be worth copying... */
-  p++;
+  start = ++p;
   while (*p && *p != ' ')
     {
-      svn_stringbuf_appendbyte(range, *p);
       p++;
     }
   if (*p != ' ')
     /* No no no... */
     return FALSE;
 
+  svn_stringbuf_appendbytes(range, start, p - start);
+
   /* Check for trailing @@ */
   p++;
   if (! starts_with(p, atat))
@@ -477,19 +482,24 @@ svn_diff_hunk_readline_diff_text(const s
   return SVN_NO_ERROR;
 }
 
-/* Parse PROP_NAME from HEADER as the part after the INDICATOR line. */
+/* Parse *PROP_NAME from HEADER as the part after the INDICATOR line.
+ * Allocate *PROP_NAME in RESULT_POOL.
+ * Set *PROP_NAME to NULL if no valid property name was found. */
 static svn_error_t *
 parse_prop_name(const char **prop_name, const char *header, 
                 const char *indicator, apr_pool_t *result_pool)
 {
-  /* ### This can fail if the filename cannot be represented in the current
-   * ### locale's encoding. */
   SVN_ERR(svn_utf_cstring_to_utf8(prop_name,
                                   header + strlen(indicator),
                                   result_pool));
-
-  /* ### Are we guarenteed that there are no trailing or leading
-   * ### whitespaces in the name? */
+  if (**prop_name == '\0')
+    *prop_name = NULL;
+  else if (! svn_prop_name_is_valid(*prop_name))
+    {
+      svn_stringbuf_t *buf = svn_stringbuf_create(*prop_name, result_pool);
+      svn_stringbuf_strip_whitespace(buf);
+      *prop_name = (svn_prop_name_is_valid(buf->data) ? buf->data : NULL);
+    }
 
   return SVN_NO_ERROR;
 }
@@ -674,20 +684,23 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
           else if (starts_with(line->data, "Added: "))
             {
               SVN_ERR(parse_prop_name(prop_name, line->data, "Added: ",
-                                      result_pool));
-              *prop_operation = svn_diff_op_added;
+                                      result_pool));  
+              if (*prop_name)
+                *prop_operation = svn_diff_op_added;
             }
           else if (starts_with(line->data, "Deleted: "))
             {
               SVN_ERR(parse_prop_name(prop_name, line->data, "Deleted: ",
                                       result_pool));
-              *prop_operation = svn_diff_op_deleted;
+              if (*prop_name)
+                *prop_operation = svn_diff_op_deleted;
             }
           else if (starts_with(line->data, "Modified: "))
             {
               SVN_ERR(parse_prop_name(prop_name, line->data, "Modified: ",
                                       result_pool));
-              *prop_operation = svn_diff_op_modified;
+              if (*prop_name)
+                *prop_operation = svn_diff_op_modified;
             }
           else if (starts_with(line->data, minus)
                    || starts_with(line->data, "diff --git "))
@@ -1027,7 +1040,7 @@ git_move_from(enum parse_state *new_stat
   return SVN_NO_ERROR;
 }
 
-/* Parse the 'rename to ' line fo a git extended unidiff. */
+/* Parse the 'rename to ' line of a git extended unidiff. */
 static svn_error_t *
 git_move_to(enum parse_state *new_state, const char *line, svn_patch_t *patch,
             apr_pool_t *result_pool, apr_pool_t *scratch_pool)
@@ -1262,6 +1275,8 @@ svn_diff_parse_next_patch(svn_patch_t **
       const char *prop_name;
       svn_diff_operation_kind_t prop_operation;
 
+      last_prop_name = NULL;
+
       /* Parse hunks. */
       (*patch)->hunks = apr_array_make(result_pool, 10,
                                        sizeof(svn_diff_hunk_t *));

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs/fs-loader.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs/fs-loader.c Thu Dec  2 20:55:08 2010
@@ -991,6 +991,22 @@ svn_fs_closest_copy(svn_fs_root_t **root
 }
 
 svn_error_t *
+svn_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog,
+                      svn_fs_root_t *root,
+                      const apr_array_header_t *paths,
+                      svn_mergeinfo_inheritance_t inherit,
+                      svn_boolean_t validate_inherited_mergeinfo,
+                      svn_boolean_t include_descendants,
+                      apr_pool_t *pool)
+{
+  return svn_error_return(root->vtable->get_mergeinfo(catalog, root, paths,
+                                                      inherit,
+                                                      validate_inherited_mergeinfo,
+                                                      include_descendants,
+                                                      pool));
+}
+
+svn_error_t *
 svn_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
                      svn_fs_root_t *root,
                      const apr_array_header_t *paths,
@@ -998,10 +1014,24 @@ svn_fs_get_mergeinfo(svn_mergeinfo_catal
                      svn_boolean_t include_descendants,
                      apr_pool_t *pool)
 {
-  return svn_error_return(root->vtable->get_mergeinfo(catalog, root, paths,
-                                                      inherit,
-                                                      include_descendants,
-                                                      pool));
+  return svn_error_return(svn_fs_get_mergeinfo2(catalog, root, paths,
+                                                inherit,
+                                                FALSE,
+                                                include_descendants,
+                                                pool));
+}
+
+svn_error_t *
+svn_fs_validate_mergeinfo(svn_mergeinfo_t *validated_mergeinfo,
+                          svn_fs_t *fs,
+                          svn_mergeinfo_t mergeinfo,
+                          apr_pool_t *result_pool,
+                          apr_pool_t *scratch_pool)
+{
+  return svn_error_return(fs->vtable->validate_mergeinfo(validated_mergeinfo,
+                                                         fs, mergeinfo,
+                                                         result_pool,
+                                                         scratch_pool));
 }
 
 svn_error_t *

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs/fs-loader.h?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs/fs-loader.h Thu Dec  2 20:55:08 2010
@@ -197,6 +197,11 @@ typedef struct fs_vtable_t
   svn_error_t *(*bdb_set_errcall)(svn_fs_t *fs,
                                   void (*handler)(const char *errpfx,
                                                   char *msg));
+  svn_error_t *(*validate_mergeinfo)(svn_mergeinfo_t *validated_mergeinfo,
+                                     svn_fs_t *fs,
+                                     svn_mergeinfo_t mergeinfo,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool);
 } fs_vtable_t;
 
 
@@ -331,6 +336,7 @@ typedef struct root_vtable_t
                                 svn_fs_root_t *root,
                                 const apr_array_header_t *paths,
                                 svn_mergeinfo_inheritance_t inherit,
+                                svn_boolean_t validate_inherited_mergeinfo,
                                 svn_boolean_t include_descendants,
                                 apr_pool_t *pool);
 } root_vtable_t;

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/dag.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/dag.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/dag.c Thu Dec  2 20:55:08 2010
@@ -481,7 +481,7 @@ make_entry(dag_node_t **child_p,
   /* Create the new node's NODE-REVISION */
   memset(&new_noderev, 0, sizeof(new_noderev));
   new_noderev.kind = is_dir ? svn_node_dir : svn_node_file;
-  new_noderev.created_path = svn_uri_join(parent_path, name, pool);
+  new_noderev.created_path = svn_fspath__join(parent_path, name, pool);
   SVN_ERR(svn_fs_base__create_node
           (&new_node_id, svn_fs_base__dag_get_fs(parent), &new_noderev,
            svn_fs_base__id_copy_id(svn_fs_base__dag_get_id(parent)),
@@ -763,7 +763,7 @@ svn_fs_base__dag_clone_child(dag_node_t 
       noderev->predecessor_id = cur_entry->id;
       if (noderev->predecessor_count != -1)
         noderev->predecessor_count++;
-      noderev->created_path = svn_uri_join(parent_path, name, pool);
+      noderev->created_path = svn_fspath__join(parent_path, name, pool);
       SVN_ERR(svn_fs_base__create_successor(&new_node_id, fs, cur_entry->id,
                                             noderev, copy_id, txn_id,
                                             trail, pool));
@@ -1422,7 +1422,7 @@ svn_fs_base__dag_copy(dag_node_t *to_nod
       noderev->predecessor_id = svn_fs_base__id_copy(src_id, pool);
       if (noderev->predecessor_count != -1)
         noderev->predecessor_count++;
-      noderev->created_path = svn_uri_join
+      noderev->created_path = svn_fspath__join
         (svn_fs_base__dag_get_created_path(to_node), entry, pool);
       SVN_ERR(svn_fs_base__create_successor(&id, fs, src_id, noderev,
                                             copy_id, txn_id, trail, pool));

Modified: subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/fs.c?rev=1041580&r1=1041579&r2=1041580&view=diff
==============================================================================
--- subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/gpg-agent-password-store/subversion/libsvn_fs_base/fs.c Thu Dec  2 20:55:08 2010
@@ -497,6 +497,7 @@ static fs_vtable_t fs_vtable = {
   svn_fs_base__get_lock,
   svn_fs_base__get_locks,
   base_bdb_set_errcall,
+  svn_fs_base__validate_mergeinfo,
 };
 
 /* Where the format number is stored. */