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

svn commit: r984468 [7/25] - in /subversion/branches/ignore-mergeinfo: ./ build/ build/generator/ build/generator/templates/ notes/ notes/tree-conflicts/ notes/wc-ng/ subversion/bindings/javahl/native/ subversion/bindings/javahl/src/org/apache/subversi...

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/prop_commands.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/prop_commands.c Wed Aug 11 16:43:22 2010
@@ -97,7 +97,7 @@ struct propset_walk_baton
   void *notify_baton;
 };
 
-/* An node-walk callback for svn_client_propset3.
+/* An node-walk callback for svn_client_propset4.
  *
  * For LOCAL_ABSPATH, set the property named wb->PROPNAME to the value
  * wb->PROPVAL, where "wb" is the WALK_BATON of type "struct
@@ -118,7 +118,8 @@ propset_walk_cb(const char *local_abspat
 
   err = svn_wc_prop_set4(wb->wc_ctx, local_abspath, wb->propname, wb->propval,
                          wb->force, wb->notify_func, wb->notify_baton, pool);
-  if (err && err->apr_err == SVN_ERR_ILLEGAL_TARGET)
+  if (err && (err->apr_err == SVN_ERR_ILLEGAL_TARGET
+              || err->apr_err == SVN_ERR_WC_INVALID_SCHEDULE))
     {
       svn_error_clear(err);
       err = SVN_NO_ERROR;
@@ -189,8 +190,7 @@ do_url_propset(const char *propname,
 }
 
 static svn_error_t *
-propset_on_url(svn_commit_info_t **commit_info_p,
-               const char *propname,
+propset_on_url(const char *propname,
                const svn_string_t *propval,
                const char *target,
                svn_boolean_t skip_checks,
@@ -204,7 +204,7 @@ propset_on_url(svn_commit_info_t **commi
   svn_node_kind_t node_kind;
   const char *message;
   const svn_delta_editor_t *editor;
-  void *commit_baton, *edit_baton;
+  void *edit_baton;
   apr_hash_t *commit_revprops;
   svn_error_t *err;
 
@@ -215,7 +215,7 @@ propset_on_url(svn_commit_info_t **commi
 
   /* Open an RA session for the URL. Note that we don't have a local
      directory, nor a place to put temp files. */
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, target,
+  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, target,
                                                NULL, NULL, FALSE, TRUE,
                                                ctx, pool));
 
@@ -268,11 +268,10 @@ propset_on_url(svn_commit_info_t **commi
                                            message, ctx, pool));
 
   /* Fetch RA commit editor. */
-  SVN_ERR(svn_client__commit_get_baton(&commit_baton, commit_info_p, pool));
   SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
                                     commit_revprops,
-                                    svn_client__commit_callback,
-                                    commit_baton,
+                                    ctx->commit_callback2,
+                                    ctx->commit_baton,
                                     NULL, TRUE, /* No lock tokens */
                                     pool));
 
@@ -290,10 +289,56 @@ propset_on_url(svn_commit_info_t **commi
   return editor->close_edit(edit_baton, pool);
 }
 
+/* Baton for set_props_cb */
+struct set_props_baton
+{
+  svn_client_ctx_t *ctx;
+  const char *local_abspath;
+  svn_depth_t depth;
+  svn_node_kind_t kind;
+  const char *propname;
+  const svn_string_t *propval;
+  svn_boolean_t skip_checks;
+  apr_hash_t *changelist_hash;
+};
+
+/* Working copy lock callback for svn_client_propset4 */
+static svn_error_t *
+set_props_cb(void *baton,
+             apr_pool_t *result_pool,
+             apr_pool_t *scratch_pool)
+{
+  struct set_props_baton *bt = baton;
+
+  if (bt->depth >= svn_depth_files && bt->kind == svn_node_dir)
+    {
+      struct propset_walk_baton wb;
+
+      wb.wc_ctx = bt->ctx->wc_ctx;
+      wb.propname = bt->propname;
+      wb.propval = bt->propval;
+      wb.force = bt->skip_checks;
+      wb.changelist_hash = bt->changelist_hash;
+      wb.notify_func = bt->ctx->notify_func2;
+      wb.notify_baton = bt->ctx->notify_baton2;
+      SVN_ERR(svn_wc__node_walk_children(bt->ctx->wc_ctx, bt->local_abspath,
+                                         FALSE, propset_walk_cb, &wb,
+                                         bt->depth, bt->ctx->cancel_func,
+                                         bt->ctx->cancel_baton, scratch_pool));
+    }
+  else if (svn_wc__changelist_match(bt->ctx->wc_ctx, bt->local_abspath,
+                                    bt->changelist_hash, scratch_pool))
+    {
+      SVN_ERR(svn_wc_prop_set4(bt->ctx->wc_ctx, bt->local_abspath,
+                               bt->propname, bt->propval, bt->skip_checks,
+                               bt->ctx->notify_func2, bt->ctx->notify_baton2,
+                               scratch_pool));
+    }
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
-svn_client_propset3(svn_commit_info_t **commit_info_p,
-                    const char *propname,
+svn_client_propset4(const char *propname,
                     const svn_string_t *propval,
                     const char *target,
                     svn_depth_t depth,
@@ -351,9 +396,8 @@ svn_client_propset3(svn_commit_info_t **
                                  _("Setting property '%s' on non-local target "
                                    "'%s' is not supported"), propname, target);
 
-      return propset_on_url(commit_info_p, propname, propval, target,
-                            skip_checks, base_revision_for_url, revprop_table,
-                            ctx, pool);
+      return propset_on_url(propname, propval, target, skip_checks,
+                            base_revision_for_url, revprop_table, ctx, pool);
     }
   else
     {
@@ -361,6 +405,7 @@ svn_client_propset3(svn_commit_info_t **
       apr_hash_t *changelist_hash = NULL;
       const char *target_abspath;
       svn_error_t *err;
+      struct set_props_baton baton;
 
       SVN_ERR(svn_dirent_get_absolute(&target_abspath, target, pool));
 
@@ -383,29 +428,18 @@ svn_client_propset3(svn_commit_info_t **
       else
         SVN_ERR(err);
 
-      if (depth >= svn_depth_files && kind == svn_node_dir)
-        {
-          struct propset_walk_baton wb;
-
-          wb.wc_ctx = ctx->wc_ctx;
-          wb.propname = propname;
-          wb.propval = propval;
-          wb.force = skip_checks;
-          wb.changelist_hash = changelist_hash;
-          wb.notify_func = ctx->notify_func2;
-          wb.notify_baton = ctx->notify_baton2;
-          SVN_ERR(svn_wc__node_walk_children(ctx->wc_ctx, target_abspath,
-                                             FALSE, propset_walk_cb, &wb,
-                                             depth, ctx->cancel_func,
-                                             ctx->cancel_baton, pool));
-        }
-      else if (svn_wc__changelist_match(ctx->wc_ctx, target_abspath,
-                                        changelist_hash, pool))
-        {
-          SVN_ERR(svn_wc_prop_set4(ctx->wc_ctx, target_abspath, propname,
-                                   propval, skip_checks, ctx->notify_func2,
-                                   ctx->notify_baton2, pool));
-        }
+      baton.ctx = ctx;
+      baton.local_abspath = target_abspath;
+      baton.depth = depth;
+      baton.kind = kind;
+      baton.propname = propname;
+      baton.propval = propval;
+      baton.skip_checks = skip_checks;
+      baton.changelist_hash = changelist_hash;
+
+      SVN_ERR(svn_wc__call_with_write_lock(set_props_cb, &baton,
+                                           ctx->wc_ctx, target_abspath, FALSE,
+                                           pool, pool));
 
       return SVN_NO_ERROR;
     }
@@ -438,7 +472,7 @@ svn_client_revprop_set2(const char *prop
 
   /* Open an RA session for the URL. Note that we don't have a local
      directory, nor a place to put temp files. */
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, URL, NULL,
+  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, URL, NULL,
                                                NULL, FALSE, TRUE, ctx, pool));
 
   /* Resolve the revision into something real, and return that to the
@@ -930,7 +964,7 @@ svn_client_revprop_get(const char *propn
 
   /* Open an RA session for the URL. Note that we don't have a local
      directory, nor a place to put temp files. */
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, URL, NULL,
+  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, URL, NULL,
                                                NULL, FALSE, TRUE, ctx, pool));
 
   /* Resolve the revision into something real, and return that to the
@@ -1274,7 +1308,7 @@ svn_client_revprop_list(apr_hash_t **pro
 
   /* Open an RA session for the URL. Note that we don't have a local
      directory, nor a place to put temp files. */
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, URL, NULL,
+  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, URL, NULL,
                                                NULL, FALSE, TRUE, ctx, pool));
 
   /* Resolve the revision into something real, and return that to the

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/ra.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/ra.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/ra.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/ra.c Wed Aug 11 16:43:22 2010
@@ -280,8 +280,12 @@ get_client_string(void *baton,
   return SVN_NO_ERROR;
 }
 
+
+#define SVN_CLIENT__MAX_REDIRECT_ATTEMPTS 3 /* ### TODO:  Make configurable. */
+
 svn_error_t *
 svn_client__open_ra_session_internal(svn_ra_session_t **ra_session,
+                                     const char **corrected_url,
                                      const char *base_url,
                                      const char *base_dir_abspath,
                                      const apr_array_header_t *commit_items,
@@ -332,9 +336,63 @@ svn_client__open_ra_session_internal(svn
         SVN_ERR(err);
     }
 
-  return svn_error_return(svn_ra_open3(ra_session, base_url, uuid, cbtable, cb,
-                                       ctx->config, pool));
-}
+  /* If the caller allows for auto-following redirections, and the
+     RA->open() call above reveals a CORRECTED_URL, try the new URL.
+     We'll do this in a loop up to some maximum number follow-and-retry
+     attempts.  */
+  if (corrected_url)
+    {
+      apr_hash_t *attempted = apr_hash_make(pool);
+      int attempts_left = SVN_CLIENT__MAX_REDIRECT_ATTEMPTS;
+
+      *corrected_url = NULL;
+      while (attempts_left--)
+        {
+          const char *corrected = NULL;
+
+          /* Try to open the RA session.  If this is our last attempt,
+             don't accept corrected URLs from the RA provider. */
+          SVN_ERR(svn_ra_open4(ra_session,
+                               attempts_left == 0 ? NULL : &corrected,
+                               base_url, uuid, cbtable, cb, ctx->config, pool));
+
+          /* No error and no corrected URL?  We're done here. */
+          if (! corrected)
+            break;
+
+          /* Notify the user that a redirect is being followed. */
+          if (ctx->notify_func2 != NULL)
+            {
+              svn_wc_notify_t *notify = 
+                svn_wc_create_notify_url(corrected, 
+                                         svn_wc_notify_url_redirect, pool);
+              (*ctx->notify_func2)(ctx->notify_baton2, notify, pool);
+            }
+
+          /* Our caller will want to know what our final corrected URL was. */
+          *corrected_url = corrected;
+
+          /* Make sure we've not attempted this URL before. */
+          if (apr_hash_get(attempted, corrected, APR_HASH_KEY_STRING))
+            return svn_error_createf(SVN_ERR_CLIENT_CYCLE_DETECTED, NULL,
+                                     _("Redirect cycle detected for URL '%s'"),
+                                     corrected);
+
+          /* Remember this CORRECTED_URL so we don't wind up in a loop. */
+          apr_hash_set(attempted, corrected, APR_HASH_KEY_STRING, (void *)1);
+          base_url = corrected;
+        }
+    }
+  else
+    {
+      SVN_ERR(svn_ra_open4(ra_session, NULL, base_url,
+                           uuid, cbtable, cb, ctx->config, pool));
+    }
+
+  return SVN_NO_ERROR;
+ }
+#undef SVN_CLIENT__MAX_REDIRECT_ATTEMPTS
+
 
 svn_error_t *
 svn_client_open_ra_session(svn_ra_session_t **session,
@@ -342,9 +400,10 @@ svn_client_open_ra_session(svn_ra_sessio
                            svn_client_ctx_t *ctx,
                            apr_pool_t *pool)
 {
-  return svn_error_return(svn_client__open_ra_session_internal(session, url,
-                                              NULL, NULL,
-                                              FALSE, TRUE, ctx, pool));
+  return svn_error_return(
+             svn_client__open_ra_session_internal(session, NULL, url,
+                                                  NULL, NULL, FALSE, TRUE,
+                                                  ctx, pool));
 }
 
 
@@ -358,7 +417,7 @@ svn_client_uuid_from_url(const char **uu
   apr_pool_t *subpool = svn_pool_create(pool);
 
   /* use subpool to create a temporary RA session */
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, url,
+  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, url,
                                                NULL, /* no base dir */
                                                NULL, FALSE, TRUE,
                                                ctx, subpool));
@@ -416,7 +475,7 @@ svn_client__ra_session_from_path(svn_ra_
   svn_opt_revision_t dead_end_rev;
   svn_opt_revision_t *ignored_rev, *new_rev;
   svn_revnum_t rev;
-  const char *ignored_url;
+  const char *ignored_url, *corrected_url;
 
   SVN_ERR(svn_client_url_from_path2(&initial_url, path_or_url, ctx, pool,
                                     pool));
@@ -431,11 +490,17 @@ svn_client__ra_session_from_path(svn_ra_
                                     TRUE,
                                     pool));
 
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, initial_url,
+  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url,
+                                               initial_url,
                                                base_dir_abspath, NULL,
                                                base_dir_abspath != NULL,
                                                FALSE, ctx, pool));
 
+  /* If we got a CORRECTED_URL, we'll want to refer to that as the
+     URL-ized form of PATH_OR_URL from now on. */
+  if (corrected_url && svn_path_is_url(path_or_url))
+    path_or_url = corrected_url;
+
   dead_end_rev.kind = svn_opt_revision_unspecified;
 
   /* Run the history function to get the object's (possibly
@@ -626,7 +691,7 @@ svn_client__repos_locations(const char *
 
   /* Open a RA session to this URL if we don't have one already. */
   if (! ra_session)
-    SVN_ERR(svn_client__open_ra_session_internal(&ra_session, url, NULL,
+    SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, url, NULL,
                                                  NULL, FALSE, TRUE,
                                                  ctx, subpool));
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/relocate.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/relocate.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/relocate.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/relocate.c Wed Aug 11 16:43:22 2010
@@ -66,6 +66,7 @@ validator_func(void *baton,
 {
   struct validator_baton_t *b = baton;
   struct url_uuid_t *url_uuid = NULL;
+  const char *disable_checks;
 
   apr_array_header_t *uuids = b->url_uuids;
   int i;
@@ -81,6 +82,16 @@ validator_func(void *baton,
         }
     }
 
+  disable_checks = getenv("SVN_I_LOVE_CORRUPTED_WORKING_COPIES_SO_DISABLE_RELOCATE_VALIDATION");
+  if (disable_checks && (strcmp(disable_checks, "yes") == 0))
+    {
+      /* Lie about URL_UUID's components, claiming they match the
+         expectations of the validation code below.  */
+      url_uuid = apr_pcalloc(pool, sizeof(*url_uuid));
+      url_uuid->root = apr_pstrdup(pool, root_url);
+      url_uuid->uuid = apr_pstrdup(pool, uuid);
+    }
+
   /* We use an RA session in a subpool to get the UUID of the
      repository at the new URL so we can force the RA session to close
      by destroying the subpool. */
@@ -88,7 +99,7 @@ validator_func(void *baton,
     {
       apr_pool_t *sesspool = svn_pool_create(pool);
       svn_ra_session_t *ra_session;
-      SVN_ERR(svn_client__open_ra_session_internal(&ra_session, url, NULL,
+      SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, url, NULL,
                                                    NULL, FALSE, TRUE,
                                                    b->ctx, sesspool));
       url_uuid = &APR_ARRAY_PUSH(uuids, struct url_uuid_t);

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff.c Wed Aug 11 16:43:22 2010
@@ -89,6 +89,17 @@ struct edit_baton {
   svn_wc_notify_func2_t notify_func;
   void *notify_baton;
 
+  /* TRUE if the operation needs to walk deleted dirs on the "old" side.
+     FALSE otherwise. */
+  svn_boolean_t walk_deleted_repos_dirs;
+
+  /* A callback used to see if the client wishes to cancel the running
+     operation. */
+  svn_cancel_func_t cancel_func;
+
+  /* A baton to pass to the cancellation callback. */
+  void *cancel_baton;
+
   apr_pool_t *pool;
 };
 
@@ -291,9 +302,11 @@ get_file_mime_types(const char **mimetyp
 }
 
 
-/* Get the repository version of a file. This makes an RA request to
- * retrieve the file contents. A pool cleanup handler is installed to
- * delete this file.
+/* Get revision REVISION of the file described by B from the repository.
+ * Set B->path_start_revision to the path of a new temporary file containing
+ * the file's text.  Set B->pristine_props to a new hash containing the
+ * file's properties.  Install a pool cleanup handler on B->pool to delete
+ * the file.
  */
 static svn_error_t *
 get_file_from_ra(struct file_baton *b, svn_revnum_t revision)
@@ -443,6 +456,87 @@ open_root(void *edit_baton,
   return SVN_NO_ERROR;
 }
 
+/* Recursively walk tree rooted at DIR (at REVISION) in the repository,
+ * reporting all files as deleted.  Part of a workaround for issue 2333.
+ *
+ * DIR is a repository path relative to the URL in RA_SESSION.  REVISION
+ * may be NULL, in which case it defaults to HEAD.  EB is the
+ * overall crawler editor baton.  If CANCEL_FUNC is not NULL, then it
+ * should refer to a cancellation function (along with CANCEL_BATON).
+ */
+/* ### TODO: Handle depth. */
+static svn_error_t *
+diff_deleted_dir(const char *dir,
+                 svn_revnum_t revision,
+                 svn_ra_session_t *ra_session,
+                 struct edit_baton *eb,
+                 svn_cancel_func_t cancel_func,
+                 void *cancel_baton,
+                 apr_pool_t *pool)
+{
+  apr_hash_t *dirents;
+  apr_pool_t *iterpool = svn_pool_create(pool);
+  apr_hash_index_t *hi;
+
+  if (cancel_func)
+    SVN_ERR(cancel_func(cancel_baton));
+
+  SVN_ERR(svn_ra_get_dir2(ra_session,
+                          &dirents,
+                          NULL, NULL,
+                          dir,
+                          revision,
+                          SVN_DIRENT_KIND,
+                          pool));
+  
+  for (hi = apr_hash_first(pool, dirents); hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *path;
+      const char *name = svn__apr_hash_index_key(hi);
+      svn_dirent_t *dirent = svn__apr_hash_index_val(hi);
+
+      svn_pool_clear(iterpool);
+
+      path = svn_relpath_join(dir, name, iterpool);
+
+      if (dirent->kind == svn_node_file)
+        {
+          struct file_baton *b;
+          const char *mimetype1, *mimetype2;
+
+          /* Compare a file being deleted against an empty file */
+          b = make_file_baton(path, FALSE, eb, iterpool);
+          SVN_ERR(get_file_from_ra(b, revision));
+
+          SVN_ERR(get_empty_file(b->edit_baton, &(b->path_end_revision)));
+      
+          get_file_mime_types(&mimetype1, &mimetype2, b);
+
+          SVN_ERR(eb->diff_callbacks->file_deleted(
+                                NULL, NULL, NULL, b->wcpath,
+                                b->path_start_revision,
+                                b->path_end_revision,
+                                mimetype1, mimetype2,
+                                b->pristine_props,
+                                b->edit_baton->diff_cmd_baton,
+                                pool));
+        }
+ 
+      if (dirent->kind == svn_node_dir)
+        SVN_ERR(diff_deleted_dir(path,
+                                 revision,
+                                 ra_session,
+                                 eb,
+                                 cancel_func,
+                                 cancel_baton,
+                                 iterpool));
+    }
+
+  svn_pool_destroy(iterpool);
+  return SVN_NO_ERROR;
+}
+
 /* An editor function.  */
 static svn_error_t *
 delete_entry(const char *path,
@@ -500,6 +594,20 @@ delete_entry(const char *path,
                     (local_dir_abspath, &state, &tree_conflicted,
                      svn_dirent_join(eb->target, path, pool),
                      eb->diff_cmd_baton, pool));
+ 
+            if (eb->walk_deleted_repos_dirs)
+              {
+                /* A workaround for issue 2333.  The "old" dir will be
+                skipped by the repository report.  Crawl it recursively,
+                diffing each file against the empty file. */
+                SVN_ERR(diff_deleted_dir(path,
+                                         eb->revision,
+                                         eb->ra_session,
+                                         eb,
+                                         eb->cancel_func,
+                                         eb->cancel_baton,
+                                         pool));
+              }
             break;
           }
         default:
@@ -1057,6 +1165,27 @@ change_file_prop(void *file_baton,
   if (b->skip)
     return SVN_NO_ERROR;
 
+  /* Issue #3657 'phantom svn:eol-style changes cause spurious merge text
+     conflicts'.  When communicating with the repository via ra_serf and
+     ra_neon, the change_dir_prop and change_file_prop svn_delta_editor_t
+     callbacks are called (obviously) when a directory or file property has
+     changed between the start and end of the edit.  Less obvious however,
+     is that these callbacks may be made describing *all* of the properties
+     on FILE_BATON->PATH when using the DAV providers, not just the change(s).
+     (Specifically ra_neon does this for diff/merge and ra_serf does it
+     for diff/merge/update/switch).
+
+     Normally this is fairly harmless, but if it appears that the
+     svn:eol-style property has changed on a file, then we can get spurious
+     text conflicts (i.e. Issue #3657).  To prevent this, we populate
+     FILE_BATON->PRISTINE_PROPS only with actual property changes. */
+  if (value)
+    {
+      const char *current_prop = svn_prop_get_value(b->pristine_props, name);
+      if (current_prop && strcmp(current_prop, value->data) == 0)
+        return SVN_NO_ERROR;
+    }
+
   propchange = apr_array_push(b->propchanges);
   propchange->name = apr_pstrdup(b->pool, name);
   propchange->value = value ? svn_string_dup(value, b->pool) : NULL;
@@ -1192,6 +1321,9 @@ svn_client__get_diff_editor(const char *
   eb->pool = subpool;
   eb->notify_func = notify_func;
   eb->notify_baton = notify_baton;
+  eb->walk_deleted_repos_dirs = TRUE;
+  eb->cancel_func = cancel_func;
+  eb->cancel_baton = cancel_baton;
 
   tree_editor->set_target_revision = set_target_revision;
   tree_editor->open_root = open_root;

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/revert.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/revert.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/revert.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/revert.c Wed Aug 11 16:43:22 2010
@@ -151,7 +151,7 @@ svn_client_revert2(const apr_array_heade
       baton.changelists = changelists;
       baton.ctx = ctx;
       err = svn_wc__call_with_write_lock(revert, &baton, ctx->wc_ctx,
-                                         local_abspath, pool, pool);
+                                         local_abspath, TRUE, pool, pool);
       if (err)
         goto errorful;
     }

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c Wed Aug 11 16:43:22 2010
@@ -230,7 +230,7 @@ reporter_finish_report(void *report_bato
 
   /* Open an RA session to our common ancestor and grab the locks under it.
    */
-  SVN_ERR(svn_client__open_ra_session_internal(&ras, rb->ancestor, NULL,
+  SVN_ERR(svn_client__open_ra_session_internal(&ras, NULL, rb->ancestor, NULL,
                                                NULL, FALSE, TRUE,
                                                rb->ctx, subpool));
 
@@ -451,7 +451,7 @@ svn_client_status5(svn_revnum_t *result_
                                     pool, pool));
 
       /* Open a repository session to the URL. */
-      SVN_ERR(svn_client__open_ra_session_internal(&ra_session, URL,
+      SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, URL,
                                                    dir_abspath,
                                                    NULL, FALSE, TRUE,
                                                    ctx, pool));

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c Wed Aug 11 16:43:22 2010
@@ -294,8 +294,9 @@ svn_client__switch_internal(svn_revnum_t
 
   /* Rely on svn_wc__acquire_write_lock setting ANCHOR_ABSPATH even
      when it returns SVN_ERR_WC_LOCKED */
-  err = svn_wc__acquire_write_lock(&anchor_abspath, ctx->wc_ctx,
-                                   local_abspath, pool, pool);
+  err = svn_wc__acquire_write_lock(&anchor_abspath,
+                                   ctx->wc_ctx, local_abspath, TRUE,
+                                   pool, pool);
   if (err && err->apr_err != SVN_ERR_WC_LOCKED)
     return svn_error_return(err);
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c Wed Aug 11 16:43:22 2010
@@ -78,8 +78,9 @@ file_fetcher(void *baton,
     SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ffb->session,
                                               session_url, ffb->pool));
   else
-    SVN_ERR(svn_client__open_ra_session_internal(&(ffb->session), session_url,
-                                                 NULL, NULL, FALSE, TRUE,
+    SVN_ERR(svn_client__open_ra_session_internal(&(ffb->session), NULL,
+                                                 session_url, NULL, NULL,
+                                                 FALSE, TRUE,
                                                  ffb->ctx, ffb->pool));
 
   return svn_ra_get_file(ffb->session, base_name, revision, stream,
@@ -107,6 +108,7 @@ update_internal(svn_revnum_t *result_rev
   const svn_ra_reporter3_t *reporter;
   void *report_baton;
   const char *anchor_url;
+  const char *corrected_url;
   const char *target;
   const char *repos_root;
   svn_error_t *err;
@@ -156,9 +158,6 @@ update_internal(svn_revnum_t *result_rev
                                  pool));
 
           /* Target excluded, we are done now */
-          SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath,
-                                             pool));
-
           return SVN_NO_ERROR;
         }
 
@@ -191,9 +190,19 @@ update_internal(svn_revnum_t *result_rev
     : NULL;
 
   /* Open an RA session for the URL */
-  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, anchor_url,
-                                               anchor_abspath, NULL, TRUE, TRUE,
-                                               ctx, pool));
+  SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url,
+                                               anchor_url,
+                                               anchor_abspath, NULL, TRUE,
+                                               TRUE, ctx, pool));
+
+  /* If we got a corrected URL from the RA subsystem, we'll need to
+     relocate our working copy first. */
+  if (corrected_url)
+    {
+      SVN_ERR(svn_client_relocate(anchor_abspath, anchor_url, corrected_url,
+                                  TRUE, ctx, pool));
+      anchor_url = corrected_url;
+    }
 
   /* ### todo: shouldn't svn_client__get_revision_number be able
      to take a URL as easily as a local path?  */
@@ -282,8 +291,6 @@ update_internal(svn_revnum_t *result_rev
   if (sleep_here)
     svn_io_sleep_for_timestamps(local_abspath, pool);
 
-  SVN_ERR(svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool));
-
   /* Let everyone know we're finished here. */
   if (ctx->notify_func2)
     {
@@ -320,31 +327,30 @@ svn_client__update_internal(svn_revnum_t
                             apr_pool_t *pool)
 {
   const char *anchor_abspath;
-  svn_error_t *err1, *err2;
+  svn_error_t *err;
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath));
 
   if (!innerupdate)
-    {
-      SVN_ERR(svn_wc__acquire_write_lock(&anchor_abspath, ctx->wc_ctx,
-                                         local_abspath, pool, pool));
-    }
+    SVN_ERR(svn_wc__acquire_write_lock(&anchor_abspath,
+                                       ctx->wc_ctx, local_abspath, TRUE,
+                                       pool, pool));
   else
-    {
-      SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx,
-                                         local_abspath, pool, pool));
-      anchor_abspath = local_abspath;
-    }
+    SVN_ERR(svn_wc__acquire_write_lock(&anchor_abspath,
+                                       ctx->wc_ctx, local_abspath, FALSE,
+                                       pool, pool));
 
-  err1 = update_internal(result_rev, local_abspath, anchor_abspath,
+  err = update_internal(result_rev, local_abspath, anchor_abspath,
                          revision, depth, depth_is_sticky,
                          ignore_externals, allow_unver_obstructions,
                          timestamp_sleep, send_copyfrom_args,
                          innerupdate, ctx, pool);
 
-  err2 = svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool);
+  err = svn_error_compose_create(
+            err,
+            svn_wc__release_write_lock(ctx->wc_ctx, anchor_abspath, pool));
 
-  return svn_error_compose_create(err1, err2);
+  return svn_error_return(err);
 }
 
 

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/url.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/url.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/url.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/url.c Wed Aug 11 16:43:22 2010
@@ -116,9 +116,10 @@ svn_client__derive_location(const char *
     {
       if (ra_session == NULL)
         {
-          SVN_ERR(svn_client__open_ra_session_internal(&ra_session, *url, NULL,
-                                                       NULL, FALSE, TRUE, ctx,
-                                                       scratch_pool));
+          SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL,
+                                                       *url, NULL, NULL,
+                                                       FALSE, TRUE,
+                                                       ctx, scratch_pool));
         }
       SVN_ERR(svn_client__get_revision_number(peg_revnum, NULL, ctx->wc_ctx,
                                               NULL, ra_session, peg_revision,

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_memory.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_memory.c Wed Aug 11 16:43:22 2010
@@ -353,6 +353,10 @@ typedef struct unified_output_baton_t
   apr_off_t hunk_length[2]; /* 0 == original; 1 == modified */
   apr_off_t hunk_start[2];  /* 0 == original; 1 == modified */
 
+  /* The delimiters of the hunk header, '@@' for text hunks and '##' for
+   * property hunks. */
+  const char *hunk_delimiter;
+
   /* Pool for allocation of temporary memory in the callbacks
      Should be cleared on entry of each iteration of a callback */
   apr_pool_t *pool;
@@ -515,8 +519,13 @@ output_unified_diff_modified(void *baton
   targ_orig = (targ_orig < 0) ? 0 : targ_orig;
   targ_mod = modified_start;
 
+  /* If the changed ranges are far enough apart (no overlapping or
+   * connecting context), flush the current hunk. */
   if (btn->next_token + SVN_DIFF__UNIFIED_CONTEXT_SIZE < targ_orig)
-    SVN_ERR(output_unified_flush_hunk(btn, NULL));
+    SVN_ERR(output_unified_flush_hunk(btn, btn->hunk_delimiter));
+  /* Adjust offset if it's not the first hunk. */
+  else if (btn->hunk_length[0] != 0)
+    targ_orig = btn->next_token;
 
   if (btn->hunk_length[0] == 0
       && btn->hunk_length[1] == 0)
@@ -569,6 +578,7 @@ svn_diff_mem_string_output_unified2(svn_
       baton.pool = svn_pool_create(pool);
       baton.header_encoding = header_encoding;
       baton.hunk = svn_stringbuf_create("", pool);
+      baton.hunk_delimiter = hunk_delimiter;
 
       SVN_ERR(svn_utf_cstring_from_utf8_ex2
               (&(baton.prefix_str[unified_output_context]), " ",

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/parse-diff.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/parse-diff.c Wed Aug 11 16:43:22 2010
@@ -33,10 +33,87 @@
 #include "svn_dirent_uri.h"
 #include "svn_diff.h"
 
+#include "private/svn_eol_private.h"
+
 /* Helper macro for readability */
 #define starts_with(str, start)  \
   (strncmp((str), (start), strlen(start)) == 0)
 
+struct svn_hunk_t {
+  /* Hunk texts (see include/svn_diff.h). */
+  svn_stream_t *diff_text;
+  svn_stream_t *original_text;
+  svn_stream_t *modified_text;
+
+  /* Whether the hunk is being interpreted in reverse. */
+  svn_boolean_t reverse;
+
+  /* Hunk ranges as they appeared in the patch file.
+   * All numbers are lines, not bytes. */
+  svn_linenum_t original_start;
+  svn_linenum_t original_length;
+  svn_linenum_t modified_start;
+  svn_linenum_t modified_length;
+
+  /* Number of lines of leading and trailing hunk context. */
+  svn_linenum_t leading_context;
+  svn_linenum_t trailing_context;
+};
+
+svn_error_t *
+svn_diff_hunk_reset_diff_text(const svn_hunk_t *hunk)
+{
+  return svn_error_return(svn_stream_reset(hunk->diff_text));
+}
+
+svn_error_t *
+svn_diff_hunk_reset_original_text(const svn_hunk_t *hunk)
+{
+  return svn_error_return(svn_stream_reset(hunk->original_text));
+}
+
+svn_error_t *
+svn_diff_hunk_reset_modified_text(const svn_hunk_t *hunk)
+{
+  return svn_error_return(svn_stream_reset(hunk->modified_text));
+}
+
+svn_linenum_t
+svn_diff_hunk_get_original_start(const svn_hunk_t *hunk)
+{
+  return hunk->original_start;
+}
+
+svn_linenum_t
+svn_diff_hunk_get_original_length(const svn_hunk_t *hunk)
+{
+  return hunk->original_length;
+}
+
+svn_linenum_t
+svn_diff_hunk_get_modified_start(const svn_hunk_t *hunk)
+{
+  return hunk->modified_start;
+}
+
+svn_linenum_t
+svn_diff_hunk_get_modified_length(const svn_hunk_t *hunk)
+{
+  return hunk->modified_length;
+}
+
+svn_linenum_t
+svn_diff_hunk_get_leading_context(const svn_hunk_t *hunk)
+{
+  return hunk->leading_context;
+}
+
+svn_linenum_t
+svn_diff_hunk_get_trailing_context(const svn_hunk_t *hunk)
+{
+  return hunk->trailing_context;
+}
+
 /* Try to parse a positive number from a decimal number encoded
  * in the string NUMBER. Return parsed number in OFFSET, and return
  * TRUE if parsing was successful. */
@@ -184,85 +261,225 @@ parse_hunk_header(const char *header, sv
   return TRUE;
 }
 
-/* A stream line-filter which allows only original text from a hunk,
- * and filters special lines (which start with a backslash). */
+/* Set *EOL to the first end-of-line string found in the stream
+ * accessed through READ_FN, MARK_FN and SEEK_FN, whose stream baton
+ * is BATON.  Leave the stream read position unchanged.
+ * Allocate *EOL statically; POOL is a scratch pool. */
 static svn_error_t *
-original_line_filter(svn_boolean_t *filtered, const char *line, void *baton,
-                     apr_pool_t *scratch_pool)
+scan_eol(const char **eol, svn_stream_t *stream, apr_pool_t *pool)
 {
-  *filtered = (line[0] == '+' || line[0] == '\\');
-  return SVN_NO_ERROR;
-}
+  const char *eol_str;
+  svn_stream_mark_t *mark;
 
-/* A stream line-filter which allows only modified text from a hunk,
- * and filters special lines (which start with a backslash). */
-static svn_error_t *
-modified_line_filter(svn_boolean_t *filtered, const char *line, void *baton,
-                     apr_pool_t *scratch_pool)
-{
-  *filtered = (line[0] == '-' || line[0] == '\\');
-  return SVN_NO_ERROR;
-}
+  SVN_ERR(svn_stream_mark(stream, &mark, pool));
 
-/** line-transformer callback to shave leading diff symbols. */
-static svn_error_t *
-remove_leading_char_transformer(svn_stringbuf_t **buf,
-                                const char *line,
-                                void *baton,
-                                apr_pool_t *result_pool,
-                                apr_pool_t *scratch_pool)
-{
-  if (line[0] == '+' || line[0] == '-' || line[0] == ' ')
-    *buf = svn_stringbuf_create(line + 1, result_pool);
-  else
-    *buf = svn_stringbuf_create(line, result_pool);
+  eol_str = NULL;
+  while (! eol_str)
+    {
+      char buf[512];
+      apr_size_t len;
+
+      len = sizeof(buf);
+      SVN_ERR(svn_stream_read(stream, buf, &len));
+      if (len == 0)
+        break; /* EOF */
+      eol_str = svn_eol__detect_eol(buf, buf + len);
+    }
+
+  SVN_ERR(svn_stream_seek(stream, mark));
+
+  *eol = eol_str;
 
   return SVN_NO_ERROR;
 }
 
-/** line-transformer callback to reverse a diff text. */
+/* A helper function similar to svn_stream_readline_detect_eol(),
+ * suitable for reading original or modified hunk text from a STREAM
+ * which has been mapped onto a hunk region within a unidiff patch file.
+ *
+ * Allocate *STRINGBUF in RESULT_POOL, and read into it one line from STREAM.
+ *
+ * STREAM is expected to contain unidiff text.
+ * Leading unidiff symbols ('+', '-', and ' ') are removed from the line,
+ * Any lines commencing with the VERBOTEN character are discarded.
+ * VERBOTEN should be '+' or '-', depending on which form of hunk text
+ * is being read.
+ *
+ * The line-terminator is detected automatically and stored in *EOL
+ * if EOL is not NULL. If EOF is reached and the stream does not end
+ * with a newline character, and EOL is not NULL, *EOL is set to NULL.
+ *
+ * SCRATCH_POOL is used for temporary allocations.
+ */
 static svn_error_t *
-reverse_diff_transformer(svn_stringbuf_t **buf,
-                         const char *line,
-                         void *baton,
-                         apr_pool_t *result_pool,
-                         apr_pool_t *scratch_pool)
+hunk_readline(svn_stream_t *stream,
+              svn_stringbuf_t **stringbuf,
+              const char **eol,
+              svn_boolean_t *eof,
+              char verboten,
+              apr_pool_t *result_pool,
+              apr_pool_t *scratch_pool)
 {
-  svn_hunk_t hunk;
+  svn_stringbuf_t *str;
+  apr_pool_t *iterpool;
+  svn_boolean_t filtered;
+  const char *eol_str;
+
+  *eof = FALSE;
+
+  iterpool = svn_pool_create(scratch_pool);
+  do
+    {
+      apr_size_t numbytes;
+      const char *match;
+      char c;
+
+      svn_pool_clear(iterpool);
+
+      /* Since we're reading one character at a time, let's at least
+         optimize for the 90% case.  90% of the time, we can avoid the
+         stringbuf ever having to realloc() itself if we start it out at
+         80 chars.  */
+      str = svn_stringbuf_create_ensure(80, iterpool);
+
+      SVN_ERR(scan_eol(&eol_str, stream, iterpool));
+      if (eol)
+        *eol = eol_str;
+      if (eol_str == NULL)
+        {
+          /* No newline until EOF, EOL_STR can be anything. */
+          eol_str = APR_EOL_STR;
+        }
+
+      /* Read into STR up to and including the next EOL sequence. */
+      match = eol_str;
+      numbytes = 1;
+      while (*match)
+        {
+          SVN_ERR(svn_stream_read(stream, &c, &numbytes));
+          if (numbytes != 1)
+            {
+              /* a 'short' read means the stream has run out. */
+              *eof = TRUE;
+              /* We know we don't have a whole EOL sequence, but ensure we
+               * don't chop off any partial EOL sequence that we may have. */
+              match = eol_str;
+              /* Process this short (or empty) line just like any other
+               * except with *EOF set. */
+              break;
+            }
+
+          if (c == *match)
+            match++;
+          else
+            match = eol_str;
+
+          svn_stringbuf_appendbytes(str, &c, 1);
+        }
+
+      svn_stringbuf_chop(str, match - eol_str);
+      filtered = (str->data[0] == verboten || str->data[0] == '\\');
+    }
+  while (filtered && ! *eof);
+  /* Not destroying the iterpool just yet since we still need STR
+   * which is allocated in it. */
 
-  /* ### Pass the already parsed hunk via the baton?
-   * ### Maybe we should really make svn_stream_readline() a proper stream
-   * ### method and override it instead of adding special callbacks? */
-  if (parse_hunk_header(line, &hunk, "@@", FALSE, scratch_pool))
+  if (filtered)
     {
-      *buf = svn_stringbuf_createf(result_pool,
-                                   "@@ -%lu,%lu +%lu,%lu @@",
-                                   hunk.modified_start,
-                                   hunk.modified_length,
-                                   hunk.original_start,
-                                   hunk.original_length);
+      /* EOF, return an empty string. */
+      *stringbuf = svn_stringbuf_create_ensure(0, result_pool);
     }
-  else if (parse_hunk_header(line, &hunk, "##", FALSE, scratch_pool))
+  else if (str->data[0] == '+' || str->data[0] == '-' || str->data[0] == ' ')
     {
-      *buf = svn_stringbuf_createf(result_pool,
-                                   "## -%lu,%lu +%lu,%lu ##",
-                                   hunk.modified_start,
-                                   hunk.modified_length,
-                                   hunk.original_start,
-                                   hunk.original_length);
+      /* Shave off leading unidiff symbols. */
+      *stringbuf = svn_stringbuf_create(str->data + 1, result_pool);
     }
-  else if (line[0] == '+')
+  else
     {
-      *buf = svn_stringbuf_create(line, result_pool);
-      (*buf)->data[0] = '-';
+      /* Return the line as-is. */
+      *stringbuf = svn_stringbuf_dup(str, result_pool);
     }
-  else if (line[0] == '-')
+
+  /* Done. RIP iterpool. */
+  svn_pool_destroy(iterpool);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_diff_hunk_readline_original_text(const svn_hunk_t *hunk,
+                                     svn_stringbuf_t **stringbuf,
+                                     const char **eol,
+                                     svn_boolean_t *eof,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool)
+{
+  return svn_error_return(hunk_readline(hunk->original_text, stringbuf,
+                                        eol, eof, hunk->reverse ? '-' : '+',
+                                        result_pool, scratch_pool));
+}
+
+svn_error_t *
+svn_diff_hunk_readline_modified_text(const svn_hunk_t *hunk,
+                                     svn_stringbuf_t **stringbuf,
+                                     const char **eol,
+                                     svn_boolean_t *eof,
+                                     apr_pool_t *result_pool,
+                                     apr_pool_t *scratch_pool)
+{
+  return svn_error_return(hunk_readline(hunk->modified_text, stringbuf,
+                                        eol, eof, hunk->reverse ? '+' : '-',
+                                        result_pool, scratch_pool));
+}
+
+svn_error_t *
+svn_diff_hunk_readline_diff_text(const svn_hunk_t *hunk,
+                                 svn_stringbuf_t **stringbuf,
+                                 const char **eol,
+                                 svn_boolean_t *eof,
+                                 apr_pool_t *result_pool,
+                                 apr_pool_t *scratch_pool)
+{
+  svn_hunk_t dummy;
+  svn_stringbuf_t *line;
+
+  SVN_ERR(svn_stream_readline_detect_eol(hunk->diff_text, &line, eol, eof,
+                                         result_pool));
+  
+  if (hunk->reverse)
     {
-      *buf = svn_stringbuf_create(line, result_pool);
-      (*buf)->data[0] = '+';
+      if (parse_hunk_header(line->data, &dummy, "@@", FALSE, scratch_pool))
+        {
+          /* Line is a hunk header, reverse it. */
+          *stringbuf = svn_stringbuf_createf(result_pool,
+                                             "@@ -%lu,%lu +%lu,%lu @@",
+                                             hunk->modified_start,
+                                             hunk->modified_length,
+                                             hunk->original_start,
+                                             hunk->original_length);
+        }
+      else if (parse_hunk_header(line->data, &dummy, "##", FALSE, scratch_pool))
+        {
+          /* Line is a hunk header, reverse it. */
+          *stringbuf = svn_stringbuf_createf(result_pool,
+                                             "## -%lu,%lu +%lu,%lu ##",
+                                             hunk->modified_start,
+                                             hunk->modified_length,
+                                             hunk->original_start,
+                                             hunk->original_length);
+        }
+      else
+        {
+          if (line->data[0] == '+')
+            line->data[0] = '-';
+          else if (line->data[0] == '-')
+            line->data[0] = '+';
+
+          *stringbuf = line;
+        }
     }
   else
-    *buf = svn_stringbuf_create(line, result_pool);
+    *stringbuf = line;
 
   return SVN_NO_ERROR;
 }
@@ -283,15 +500,19 @@ parse_prop_name(const char **prop_name, 
 }
 
 /* Return the next *HUNK from a PATCH, using STREAM to read data
- * from the patch file. If no hunk can be found, set *HUNK to NULL. If we
- * have a property hunk, PROP_NAME will be set. If we have a text hunk,
- * PROP_NAME will be NULL. If REVERSE is TRUE, invert the hunk while
- * parsing it. If IGNORE_WHiTESPACES is TRUE, let lines without leading
- * spaces be recognized as context lines.  Allocate results in RESULT_POOL.
- * Use SCRATCH_POOL for all other allocations. */
+ * from the patch file. If no hunk can be found, set *HUNK to NULL. Set
+ * IS_PROPERTY to TRUE if we have a property hunk. If the returned HUNK is
+ * the first belonging to a certain property, then PROP_NAME and
+ * PROP_OPERATION will be set too. If we have a text hunk, PROP_NAME will be
+ * NULL. If REVERSE is TRUE, invert the hunk while parsing it. If
+ * IGNORE_WHiTESPACES is TRUE, let lines without leading spaces be
+ * recognized as context lines.  Allocate results in
+ * RESULT_POOL.  Use SCRATCH_POOL for all other allocations. */
 static svn_error_t *
 parse_next_hunk(svn_hunk_t **hunk,
+                svn_boolean_t *is_property,
                 const char **prop_name,
+                svn_diff_operation_kind_t *prop_operation,
                 svn_patch_t *patch,
                 svn_stream_t *stream,
                 svn_boolean_t reverse,
@@ -316,11 +537,11 @@ parse_next_hunk(svn_hunk_t **hunk,
   svn_boolean_t changed_line_seen;
   apr_pool_t *iterpool;
 
-  /* We only set this if we have a property hunk. 
-   * ### prop_name acts as both a state flag inside this function and a
-   * ### qualifier to discriminate between props and text hunks. Is that
-   * ### kind of overloading ok? */
+  *prop_operation = svn_diff_op_unchanged;
+
+  /* We only set this if we have a property hunk header. */
   *prop_name = NULL;
+  *is_property = FALSE;
 
   if (apr_file_eof(patch->patch_file) == APR_EOF)
     {
@@ -449,10 +670,10 @@ parse_next_hunk(svn_hunk_t **hunk,
                 {
                   original_lines = (*hunk)->original_length;
                   modified_lines = (*hunk)->modified_length;
-                  *prop_name = NULL;
+                  *is_property = FALSE;
                 }
               }
-          else if (starts_with(line->data, prop_atat) && *prop_name)
+          else if (starts_with(line->data, prop_atat))
             {
               /* Looks like we have a property hunk header, try to rip it
                * apart. */
@@ -462,22 +683,26 @@ parse_next_hunk(svn_hunk_t **hunk,
                 {
                   original_lines = (*hunk)->original_length;
                   modified_lines = (*hunk)->modified_length;
+                  *is_property = TRUE;
                 }
             }
           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;
             }
           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;
             }
           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;
             }
           else if (starts_with(line->data, minus)
                    || starts_with(line->data, "git --diff "))
@@ -515,9 +740,6 @@ parse_next_hunk(svn_hunk_t **hunk,
       original_text = svn_stream_from_aprfile_range_readonly(f, FALSE,
                                                              start, end,
                                                              result_pool);
-      svn_stream_set_line_filter_callback(original_text, original_line_filter);
-      svn_stream_set_line_transformer_callback(original_text,
-                                               remove_leading_char_transformer);
 
       /* Create a stream which returns the modified hunk text. */
       SVN_ERR(svn_io_file_open(&f, patch->path, flags, APR_OS_DEFAULT,
@@ -525,23 +747,11 @@ parse_next_hunk(svn_hunk_t **hunk,
       modified_text = svn_stream_from_aprfile_range_readonly(f, FALSE,
                                                              start, end,
                                                              result_pool);
-      svn_stream_set_line_filter_callback(modified_text, modified_line_filter);
-      svn_stream_set_line_transformer_callback(modified_text,
-                                               remove_leading_char_transformer);
-      /* Set the hunk's texts. */
+
       (*hunk)->diff_text = diff_text;
-      if (reverse)
-        {
-          svn_stream_set_line_transformer_callback(diff_text,
-                                                   reverse_diff_transformer);
-          (*hunk)->original_text = modified_text;
-          (*hunk)->modified_text = original_text;
-        }
-      else
-        {
-          (*hunk)->original_text = original_text;
-          (*hunk)->modified_text = modified_text;
-        }
+      (*hunk)->reverse = reverse;
+      (*hunk)->original_text = original_text;
+      (*hunk)->modified_text = modified_text;
       (*hunk)->leading_context = leading_context;
       (*hunk)->trailing_context = trailing_context;
     }
@@ -598,9 +808,9 @@ enum parse_state
 
 struct transition
 {
-  const char *line;
-  enum parse_state state;
-  svn_error_t *(*fn)(enum parse_state *state, const char *line, 
+  const char *expected_input;
+  enum parse_state required_state;
+  svn_error_t *(*fn)(enum parse_state *new_state, const char *input, 
                      svn_patch_t *patch, apr_pool_t *result_pool,
                      apr_pool_t *scratch_pool);
 };
@@ -630,7 +840,7 @@ grab_filename(const char **file_name, co
 
 /* Parse the '--- ' line of a regular unidiff. */
 static svn_error_t *
-diff_minus(enum parse_state *state, const char *line, svn_patch_t *patch,
+diff_minus(enum parse_state *new_state, const char *line, svn_patch_t *patch,
            apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
   /* If we can find a tab, it separates the filename from
@@ -642,14 +852,14 @@ diff_minus(enum parse_state *state, cons
   SVN_ERR(grab_filename(&patch->old_filename, line + strlen("--- "),
                         result_pool, scratch_pool));
 
-  *state = state_minus_seen;
+  *new_state = state_minus_seen;
 
   return SVN_NO_ERROR;
 }
 
 /* Parse the '+++ ' line of a regular unidiff. */
 static svn_error_t *
-diff_plus(enum parse_state *state, const char *line, svn_patch_t *patch,
+diff_plus(enum parse_state *new_state, const char *line, svn_patch_t *patch,
            apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
   /* If we can find a tab, it separates the filename from
@@ -661,20 +871,22 @@ diff_plus(enum parse_state *state, const
   SVN_ERR(grab_filename(&patch->new_filename, line + strlen("+++ "),
                         result_pool, scratch_pool));
 
-  *state = state_unidiff_found;
+  *new_state = state_unidiff_found;
 
   return SVN_NO_ERROR;
 }
 
 /* Parse the first line of a git extended unidiff. */
 static svn_error_t *
-git_start(enum parse_state *state, const char *line, svn_patch_t *patch,
+git_start(enum parse_state *new_state, const char *line, svn_patch_t *patch,
           apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
-  const char *old_path;
-  const char *new_path;
-  char *end_old_path;
-  char *slash;
+  const char *old_path_start;
+  char *old_path_end;
+  const char *new_path_start;
+  const char *new_path_end;
+  char *new_path_marker;
+  const char *old_path_marker;
 
   /* ### Add handling of escaped paths
    * http://www.kernel.org/pub/software/scm/git/docs/git-diff.html: 
@@ -687,159 +899,231 @@ git_start(enum parse_state *state, const
   /* Our line should look like this: 'git --diff a/path b/path'. 
    * If we find any deviations from that format, we return with state reset
    * to start.
-   *
-   * ### We can't handle paths with spaces!
    */
-  slash = strchr(line, '/');
+  old_path_marker = strstr(line, " a/");
 
-  if (! slash)
+  if (! old_path_marker)
     {
-      *state = state_start;
+      *new_state = state_start;
       return SVN_NO_ERROR;
     }
 
-  old_path = slash + 1;
-
-  if (! *old_path)
+  if (! *(old_path_marker + 3))
     {
-      *state = state_start;
+      *new_state = state_start;
       return SVN_NO_ERROR;
     }
 
-  end_old_path = strchr(old_path, ' ');
+  new_path_marker = strstr(old_path_marker, " b/");
 
-  if (end_old_path)
-    *end_old_path = '\0';
-  else
+  if (! new_path_marker)
     {
-      *state = state_start;
+      *new_state = state_start;
       return SVN_NO_ERROR;
     }
 
-  /* The new path begins after the first slash after the old path. */
-  slash = strchr(end_old_path + 1, '/');
-
-  if (! slash)
+  if (! *(new_path_marker + 3))
     {
-      *state = state_start;
+      *new_state = state_start;
       return SVN_NO_ERROR;
     }
 
-  /* The path starts after the slash */
-  new_path = slash + 1;
+  /* By now, we know that we have a line on the form '--git diff a/.+ b/.+'
+   * We only need the filenames when we have deleted or added empty
+   * files. In those cases the old_path and new_path is identical on the
+   * '--git diff' line.  For all other cases we fetch the filenames from
+   * other header lines. */ 
+  old_path_start = line + strlen("--git diff a/");
+  new_path_end = line + strlen(line);
+  new_path_start = old_path_start;
+
+  while (TRUE)
+    {
+      int len_old;
+      int len_new;
+
+      new_path_marker = strstr(new_path_start, " b/");
+
+      /* No new path marker, bail out. */
+      if (! new_path_marker)
+        break;
+
+      old_path_end = new_path_marker;
+      new_path_start = new_path_marker + strlen(" b/");
+
+      /* No path after the marker. */
+      if (! *new_path_start)
+        break;
+
+      len_old = old_path_end - old_path_start;
+      len_new = new_path_end - new_path_start;
+
+      /* Are the paths before and after the " b/" marker the same? */
+      if (len_old == len_new
+          && ! strncmp(old_path_start, new_path_start, len_old))
+        {
+          *old_path_end = '\0';
+          SVN_ERR(grab_filename(&patch->old_filename, old_path_start,
+                                result_pool, scratch_pool));
 
-  if (! *new_path)
-    {
-      *state = state_start;
-      return SVN_NO_ERROR;
+          SVN_ERR(grab_filename(&patch->new_filename, new_path_start,
+                                result_pool, scratch_pool));
+          break;
+        }
     }
 
-  SVN_ERR(grab_filename(&patch->old_filename, old_path,
-                        result_pool, scratch_pool));
-
-  SVN_ERR(grab_filename(&patch->new_filename, new_path,
-                        result_pool, scratch_pool));
-
   /* We assume that the path is only modified until we've found a 'tree'
    * header */
   patch->operation = svn_diff_op_modified;
 
-  *state = state_git_diff_seen;
+  *new_state = state_git_diff_seen;
   return SVN_NO_ERROR;
 }
 
 /* Parse the '--- ' line of a git extended unidiff. */
 static svn_error_t *
-git_minus(enum parse_state *state, const char *line, svn_patch_t *patch,
+git_minus(enum parse_state *new_state, const char *line, svn_patch_t *patch,
           apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
-  /* ### Check that the path is consistent with the 'git --diff ' line. */
+  /* If we can find a tab, it separates the filename from
+   * the rest of the line which we can discard. */
+  char *tab = strchr(line, '\t');
+  if (tab)
+    *tab = '\0';
 
-  *state = state_git_minus_seen;
+  if (starts_with(line, "--- /dev/null"))
+    SVN_ERR(grab_filename(&patch->old_filename, "/dev/null",
+                          result_pool, scratch_pool));
+  else
+    SVN_ERR(grab_filename(&patch->old_filename, line + strlen("--- a/"),
+                          result_pool, scratch_pool));
+
+  *new_state = state_git_minus_seen;
   return SVN_NO_ERROR;
 }
 
 /* Parse the '+++ ' line of a git extended unidiff. */
 static svn_error_t *
-git_plus(enum parse_state *state, const char *line, svn_patch_t *patch,
+git_plus(enum parse_state *new_state, const char *line, svn_patch_t *patch,
           apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
-  /* ### Check that the path is consistent with the 'git --diff ' line. */
+  /* If we can find a tab, it separates the filename from
+   * the rest of the line which we can discard. */
+  char *tab = strchr(line, '\t');
+  if (tab)
+    *tab = '\0';
+
+  if (starts_with(line, "+++ /dev/null"))
+    SVN_ERR(grab_filename(&patch->new_filename, "/dev/null",
+                          result_pool, scratch_pool));
+  else
+    SVN_ERR(grab_filename(&patch->new_filename, line + strlen("+++ b/"),
+                          result_pool, scratch_pool));
 
-  *state = state_git_header_found;
+  *new_state = state_git_header_found;
   return SVN_NO_ERROR;
 }
 
 /* Parse the 'move from ' line of a git extended unidiff. */
 static svn_error_t *
-git_move_from(enum parse_state *state, const char *line, svn_patch_t *patch,
+git_move_from(enum parse_state *new_state, const char *line, svn_patch_t *patch,
               apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
-  /* ### Check that the path is consistent with the 'git --diff ' line. */
+  SVN_ERR(grab_filename(&patch->old_filename, line + strlen("rename from "),
+                        result_pool, scratch_pool));
 
-  *state = state_move_from_seen;
+  *new_state = state_move_from_seen;
   return SVN_NO_ERROR;
 }
 
 /* Parse the 'move to ' line fo a git extended unidiff. */
 static svn_error_t *
-git_move_to(enum parse_state *state, const char *line, svn_patch_t *patch,
+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)
 {
-  /* ### Check that the path is consistent with the 'git --diff ' line. */
+  SVN_ERR(grab_filename(&patch->new_filename, line + strlen("rename to "),
+                        result_pool, scratch_pool));
 
   patch->operation = svn_diff_op_moved;
 
-  *state = state_git_tree_seen;
+  *new_state = state_git_tree_seen;
   return SVN_NO_ERROR;
 }
 
 /* Parse the 'copy from ' line of a git extended unidiff. */
 static svn_error_t *
-git_copy_from(enum parse_state *state, const char *line, svn_patch_t *patch,
+git_copy_from(enum parse_state *new_state, const char *line, svn_patch_t *patch,
               apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
-  /* ### Check that the path is consistent with the 'git --diff ' line. */
+  SVN_ERR(grab_filename(&patch->old_filename, line + strlen("copy from "),
+                        result_pool, scratch_pool));
 
-  *state = state_copy_from_seen; 
+  *new_state = state_copy_from_seen; 
   return SVN_NO_ERROR;
 }
 
 /* Parse the 'copy to ' line of a git extended unidiff. */
 static svn_error_t *
-git_copy_to(enum parse_state *state, const char *line, svn_patch_t *patch,
+git_copy_to(enum parse_state *new_state, const char *line, svn_patch_t *patch,
             apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
-  /* ### Check that the path is consistent with the 'git --diff ' line. */
+  SVN_ERR(grab_filename(&patch->new_filename, line + strlen("copy to "),
+                        result_pool, scratch_pool));
 
   patch->operation = svn_diff_op_copied;
 
-  *state = state_git_tree_seen;
+  *new_state = state_git_tree_seen;
   return SVN_NO_ERROR;
 }
 
 /* Parse the 'new file ' line of a git extended unidiff. */
 static svn_error_t *
-git_new_file(enum parse_state *state, const char *line, svn_patch_t *patch,
+git_new_file(enum parse_state *new_state, const char *line, svn_patch_t *patch,
              apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
   patch->operation = svn_diff_op_added;
 
-  *state = state_git_header_found;
+  *new_state = state_git_tree_seen;
   return SVN_NO_ERROR;
 }
 
 /* Parse the 'deleted file ' line of a git extended unidiff. */
 static svn_error_t *
-git_deleted_file(enum parse_state *state, const char *line, svn_patch_t *patch,
+git_deleted_file(enum parse_state *new_state, const char *line, svn_patch_t *patch,
                  apr_pool_t *result_pool, apr_pool_t *scratch_pool)
 {
   patch->operation = svn_diff_op_deleted;
 
-  *state = state_git_header_found;
+  *new_state = state_git_tree_seen;
   return SVN_NO_ERROR;
 }
 
+/* Add a HUNK associated with the property PROP_NAME to PATCH. */
+static svn_error_t *
+add_property_hunk(svn_patch_t *patch, const char *prop_name, 
+                  svn_hunk_t *hunk, svn_diff_operation_kind_t operation,
+                  apr_pool_t *result_pool)
+{
+  svn_prop_patch_t *prop_patch;
+
+  prop_patch = apr_hash_get(patch->prop_patches, prop_name,
+                            APR_HASH_KEY_STRING);
+
+  if (! prop_patch)
+    {
+      prop_patch = apr_palloc(result_pool, sizeof(svn_prop_patch_t));
+      prop_patch->name = prop_name;
+      prop_patch->operation = operation;
+      prop_patch->hunks = apr_array_make(result_pool, 1, sizeof(svn_hunk_t *));
+
+      apr_hash_set(patch->prop_patches, prop_name, APR_HASH_KEY_STRING,
+                   prop_patch);
+    }
+
+  APR_ARRAY_PUSH(prop_patch->hunks, svn_hunk_t *) = hunk;
+
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_diff_parse_next_patch(svn_patch_t **patch,
@@ -859,13 +1143,8 @@ svn_diff_parse_next_patch(svn_patch_t **
 
   enum parse_state state = state_start;
 
-  /* ### dannas: As I've understood the git diff format, the first line
-   * ### contains both paths and the paths in the headers that follow are only
-   * ### there to ensure that the path is valid. Not sure though, the
-   * ### research continues... */
-
   /* Our table consisting of:
-   * Input             Required state           function to call */
+   * Expected Input     Required state          Function to call */
   struct transition transitions[] = 
     {
       {"--- ",          state_start,            diff_minus},
@@ -873,9 +1152,11 @@ svn_diff_parse_next_patch(svn_patch_t **
       {"git --diff",    state_start,            git_start},
       {"--- a/",        state_git_diff_seen,    git_minus},
       {"--- a/",        state_git_tree_seen,    git_minus},
+      {"--- /dev/null", state_git_tree_seen,    git_minus},
       {"+++ b/",        state_git_minus_seen,   git_plus},
-      {"move from ",    state_git_diff_seen,    git_move_from},
-      {"move to ",      state_move_from_seen,   git_move_to},
+      {"+++ /dev/null", state_git_minus_seen,   git_plus},
+      {"rename from ",  state_git_diff_seen,    git_move_from},
+      {"rename to ",    state_move_from_seen,   git_move_to},
       {"copy from ",    state_git_diff_seen,    git_copy_from},
       {"copy to ",      state_copy_from_seen,   git_copy_to},
       {"new file ",     state_git_diff_seen,    git_new_file},
@@ -929,11 +1210,11 @@ svn_diff_parse_next_patch(svn_patch_t **
         }
 
       /* Run the state machine. */
-      for (i = 0; i < sizeof(transitions)/sizeof(transitions[0]); i++)
+      for (i = 0; i < (sizeof(transitions) / sizeof(transitions[0])); i++)
         {
-          if (line->len > strlen(transitions[i].line) 
-              && starts_with(line->data, transitions[i].line)
-              && state == transitions[i].state)
+          if (line->len > strlen(transitions[i].expected_input) 
+              && starts_with(line->data, transitions[i].expected_input)
+              && state == transitions[i].required_state)
             {
               SVN_ERR(transitions[i].fn(&state, line->data, *patch,
                                         result_pool, iterpool));
@@ -979,36 +1260,37 @@ svn_diff_parse_next_patch(svn_patch_t **
   else
     {
       svn_hunk_t *hunk;
+      svn_boolean_t is_property;
+      const char *last_prop_name;
       const char *prop_name;
+      svn_diff_operation_kind_t prop_operation;
 
       /* Parse hunks. */
       (*patch)->hunks = apr_array_make(result_pool, 10, sizeof(svn_hunk_t *));
-      (*patch)->property_hunks = apr_hash_make(result_pool);
+      (*patch)->prop_patches = apr_hash_make(result_pool);
       do
         {
           svn_pool_clear(iterpool);
 
-          SVN_ERR(parse_next_hunk(&hunk, &prop_name, *patch, stream,
-                                  reverse, ignore_whitespace,
+          SVN_ERR(parse_next_hunk(&hunk, &is_property, &prop_name,
+                                  &prop_operation, *patch, stream, reverse,
+                                  ignore_whitespace,
                                   result_pool, iterpool));
-          if (hunk && prop_name)
-            {
-              apr_array_header_t *hunks;
-
-              hunks = apr_hash_get((*patch)->property_hunks, prop_name,
-                                    APR_HASH_KEY_STRING);
-              if (! hunks)
-                {
-                  hunks = apr_array_make(result_pool, 1, 
-                                          sizeof(svn_hunk_t *));
-                  apr_hash_set((*patch)->property_hunks, prop_name,
-                                       APR_HASH_KEY_STRING, hunks);
-                }
 
-              APR_ARRAY_PUSH(hunks, svn_hunk_t *) = hunk;
+          if (hunk && is_property)
+            {
+              if (! prop_name)
+                prop_name = last_prop_name;
+              else
+                last_prop_name = prop_name;
+              SVN_ERR(add_property_hunk(*patch, prop_name, hunk, prop_operation,
+                                        result_pool));
             }
           else if (hunk)
-            APR_ARRAY_PUSH((*patch)->hunks, svn_hunk_t *) = hunk;
+            {
+              APR_ARRAY_PUSH((*patch)->hunks, svn_hunk_t *) = hunk;
+              last_prop_name = NULL;
+            }
 
         }
       while (hunk);

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/lock-tokens-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/lock-tokens-table.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/lock-tokens-table.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/lock-tokens-table.c Wed Aug 11 16:43:22 2010
@@ -104,7 +104,7 @@ svn_fs_bdb__lock_token_delete(svn_fs_t *
   svn_fs_base__trail_debug(trail, "lock-tokens", "del");
   db_err = bfd->lock_tokens->del(bfd->lock_tokens, trail->db_txn, &key, 0);
   if (db_err == DB_NOTFOUND)
-    return SVN_FS__ERR_NO_SUCH_LOCK(fs, path);
+    return SVN_FS__ERR_NO_SUCH_LOCK(fs, path, pool);
   return BDB_WRAP(fs, "deleting entry from 'lock-tokens' table", db_err);
 }
 
@@ -131,7 +131,7 @@ svn_fs_bdb__lock_token_get(const char **
   svn_fs_base__track_dbt(&value, pool);
 
   if (db_err == DB_NOTFOUND)
-    return SVN_FS__ERR_NO_SUCH_LOCK(fs, path);
+    return SVN_FS__ERR_NO_SUCH_LOCK(fs, path, pool);
   SVN_ERR(BDB_WRAP(fs, "reading lock token", db_err));
 
   lock_token = apr_pstrmemdup(pool, value.data, value.size);

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/bdb/locks-table.c Wed Aug 11 16:43:22 2010
@@ -152,7 +152,7 @@ svn_fs_bdb__lock_get(svn_lock_t **lock_p
   if (lock->expiration_date && (apr_time_now() > lock->expiration_date))
     {
       SVN_ERR(svn_fs_bdb__lock_delete(fs, lock_token, trail, pool));
-      return SVN_FS__ERR_LOCK_EXPIRED(fs, lock_token);
+      return SVN_FS__ERR_LOCK_EXPIRED(fs, lock_token, pool);
     }
 
   *lock_p = lock;

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/lock.c Wed Aug 11 16:43:22 2010
@@ -92,7 +92,7 @@ txn_body_lock(void *baton, trail_t *trai
   /* Until we implement directory locks someday, we only allow locks
      on files or non-existent paths. */
   if (kind == svn_node_dir)
-    return SVN_FS__ERR_NOT_FILE(trail->fs, args->path);
+    return SVN_FS__ERR_NOT_FILE(trail->fs, args->path, trail->pool);
 
   /* While our locking implementation easily supports the locking of
      nonexistent paths, we deliberately choose not to allow such madness. */
@@ -112,7 +112,7 @@ txn_body_lock(void *baton, trail_t *trai
 
   /* There better be a username attached to the fs. */
   if (!trail->fs->access_ctx || !trail->fs->access_ctx->username)
-    return SVN_FS__ERR_NO_USER(trail->fs);
+    return SVN_FS__ERR_NO_USER(trail->fs, trail->pool);
 
   /* Is the caller attempting to lock an out-of-date working file? */
   if (SVN_IS_VALID_REVNUM(args->current_rev))
@@ -178,7 +178,8 @@ txn_body_lock(void *baton, trail_t *trai
         {
           /* Sorry, the path is already locked. */
           return SVN_FS__ERR_PATH_ALREADY_LOCKED(trail->fs,
-                                                      existing_lock);
+                                                 existing_lock,
+                                                 trail->pool);
         }
       else
         {
@@ -280,21 +281,22 @@ txn_body_unlock(void *baton, trail_t *tr
       if (args->token == NULL)
         return svn_fs_base__err_no_lock_token(trail->fs, args->path);
       else if (strcmp(lock_token, args->token) != 0)
-        return SVN_FS__ERR_NO_SUCH_LOCK(trail->fs, args->path);
+        return SVN_FS__ERR_NO_SUCH_LOCK(trail->fs, args->path, trail->pool);
 
       SVN_ERR(svn_fs_bdb__lock_get(&lock, trail->fs, lock_token,
                                    trail, trail->pool));
 
       /* There better be a username attached to the fs. */
       if (!trail->fs->access_ctx || !trail->fs->access_ctx->username)
-        return SVN_FS__ERR_NO_USER(trail->fs);
+        return SVN_FS__ERR_NO_USER(trail->fs, trail->pool);
 
       /* And that username better be the same as the lock's owner. */
       if (strcmp(trail->fs->access_ctx->username, lock->owner) != 0)
-        return SVN_FS__ERR_LOCK_OWNER_MISMATCH
-          (trail->fs,
+        return SVN_FS__ERR_LOCK_OWNER_MISMATCH(
+           trail->fs,
            trail->fs->access_ctx->username,
-           lock->owner);
+           lock->owner,
+           trail->pool);
     }
 
   /* Remove a row from each of the locking tables. */

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.c?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_base/tree.c Wed Aug 11 16:43:22 2010
@@ -430,7 +430,7 @@ mutable_root_node(dag_node_t **node_p,
                                        trail, pool);
   else
     /* If it's not a transaction root, we can't change its contents.  */
-    return SVN_FS__ERR_NOT_MUTABLE(root->fs, root->rev, error_path);
+    return SVN_FS__ERR_NOT_MUTABLE(root->fs, root->rev, error_path, pool);
 }
 
 
@@ -768,7 +768,7 @@ open_path(parent_path_t **parent_path_p,
 
       /* The path isn't finished yet; we'd better be in a directory.  */
       if (svn_fs_base__dag_node_kind(child) != svn_node_dir)
-        SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far),
+        SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far, pool),
                   apr_psprintf(pool, _("Failure opening '%s'"), path));
 
       rest = next;

Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_fs/fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_fs/fs.h?rev=984468&r1=984467&r2=984468&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_fs_fs/fs.h Wed Aug 11 16:43:22 2010
@@ -125,6 +125,9 @@ extern "C" {
 /* The minimum format number that supports packed revprop shards. */
 #define SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT 5
 
+/* The minimum format number that supports a configuration file (fsfs.conf) */
+#define SVN_FS_FS__MIN_CONFIG_FILE 4
+
 /* Private FSFS-specific data shared between all svn_txn_t objects that
    relate to a particular transaction in a filesystem (as identified
    by transaction id and filesystem UUID).  Objects of this type are