You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2012/03/06 18:50:31 UTC

svn commit: r1297604 [6/12] - in /subversion/branches/reintegrate-keep-alive: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/win32/ notes/ notes/api-errata/1.7/ subversion/bindings/javahl/native/ subversion/bindings/javahl...

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_neon/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_neon/util.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_neon/util.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_neon/util.c Tue Mar  6 17:50:23 2012
@@ -38,6 +38,7 @@
 #include "svn_utf.h"
 #include "svn_xml.h"
 #include "svn_props.h"
+#include "../libsvn_ra/ra_loader.h"
 
 #include "private/svn_fspath.h"
 #include "svn_private_config.h"
@@ -1649,3 +1650,13 @@ svn_ra_neon__get_deadprop_count_support(
 
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_ra_neon__register_editor_shim_callbacks(svn_ra_session_t *session,
+                                    svn_delta_shim_callbacks_t *callbacks)
+{
+  svn_ra_neon__session_t *ras = session->priv;
+
+  ras->shim_callbacks = callbacks;
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/commit.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/commit.c Tue Mar  6 17:50:23 2012
@@ -328,7 +328,7 @@ checkout_dir(dir_context_t *dir)
       return SVN_NO_ERROR;
     }
 
-  /* Is this directory or one of our parent dirs newly added? 
+  /* Is this directory or one of our parent dirs newly added?
    * If so, we're already implicitly checked out. */
   while (p_dir)
     {
@@ -2319,8 +2319,6 @@ svn_ra_serf__get_commit_editor(svn_ra_se
   svn_delta_editor_t *editor;
   commit_context_t *ctx;
   apr_hash_index_t *hi;
-  svn_delta_shim_callbacks_t *shim_callbacks =
-                                    svn_delta_shim_callbacks_default(pool);
 
   ctx = apr_pcalloc(pool, sizeof(*ctx));
 
@@ -2368,7 +2366,8 @@ svn_ra_serf__get_commit_editor(svn_ra_se
   *edit_baton = ctx;
 
   SVN_ERR(svn_editor__insert_shims(ret_editor, edit_baton, *ret_editor,
-                                   *edit_baton, shim_callbacks, pool, pool));
+                                   *edit_baton, session->shim_callbacks,
+                                   pool, pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/locks.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/locks.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/locks.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/locks.c Tue Mar  6 17:50:23 2012
@@ -412,7 +412,7 @@ handle_lock(serf_request_t *request,
       if (err && APR_STATUS_IS_EOF(err->apr_err))
         {
           ctx->done = TRUE;
-          err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED,
+          err = svn_error_createf(SVN_ERR_RA_DAV_FORBIDDEN,
                                   err,
                                   _("Lock request failed: %d %s"),
                                   ctx->status_code, ctx->reason);
@@ -572,44 +572,43 @@ svn_ra_serf__lock(svn_ra_session_t *ra_s
                   svn_boolean_t force,
                   svn_ra_lock_callback_t lock_func,
                   void *lock_baton,
-                  apr_pool_t *pool)
+                  apr_pool_t *scratch_pool)
 {
   svn_ra_serf__session_t *session = ra_session->priv;
   apr_hash_index_t *hi;
-  apr_pool_t *subpool;
+  apr_pool_t *iterpool;
 
-  subpool = svn_pool_create(pool);
+  iterpool = svn_pool_create(scratch_pool);
 
   /* ### TODO for issue 2263: Send all the locks over the wire at once.  This
      loop is just a temporary shim. */
-  for (hi = apr_hash_first(pool, path_revs); hi; hi = apr_hash_next(hi))
+  for (hi = apr_hash_first(scratch_pool, path_revs);
+       hi;
+       hi = apr_hash_next(hi))
     {
       svn_ra_serf__handler_t *handler;
       svn_ra_serf__xml_parser_t *parser_ctx;
       const char *req_url;
       lock_info_t *lock_ctx;
-      const void *key;
-      void *val;
       svn_error_t *err;
       svn_error_t *new_err = NULL;
 
-      svn_pool_clear(subpool);
+      svn_pool_clear(iterpool);
 
-      lock_ctx = apr_pcalloc(subpool, sizeof(*lock_ctx));
+      lock_ctx = apr_pcalloc(iterpool, sizeof(*lock_ctx));
 
-      apr_hash_this(hi, &key, NULL, &val);
-      lock_ctx->pool = subpool;
-      lock_ctx->path = key;
-      lock_ctx->revision = *((svn_revnum_t*)val);
-      lock_ctx->lock = svn_lock_create(subpool);
-      lock_ctx->lock->path = key;
+      lock_ctx->pool = iterpool;
+      lock_ctx->path = svn__apr_hash_index_key(hi);
+      lock_ctx->revision = *((svn_revnum_t*)svn__apr_hash_index_val(hi));
+      lock_ctx->lock = svn_lock_create(iterpool);
+      lock_ctx->lock->path = lock_ctx->path;
       lock_ctx->lock->comment = comment;
 
       lock_ctx->force = force;
       req_url = svn_path_url_add_component2(session->session_url.path,
-                                            lock_ctx->path, subpool);
+                                            lock_ctx->path, iterpool);
 
-      handler = apr_pcalloc(subpool, sizeof(*handler));
+      handler = apr_pcalloc(iterpool, sizeof(*handler));
 
       handler->method = "LOCK";
       handler->path = req_url;
@@ -617,9 +616,9 @@ svn_ra_serf__lock(svn_ra_session_t *ra_s
       handler->conn = session->conns[0];
       handler->session = session;
 
-      parser_ctx = apr_pcalloc(subpool, sizeof(*parser_ctx));
+      parser_ctx = apr_pcalloc(iterpool, sizeof(*parser_ctx));
 
-      parser_ctx->pool = subpool;
+      parser_ctx->pool = iterpool;
       parser_ctx->user_data = lock_ctx;
       parser_ctx->start = start_lock;
       parser_ctx->end = end_lock;
@@ -636,16 +635,18 @@ svn_ra_serf__lock(svn_ra_session_t *ra_s
       handler->response_baton = parser_ctx;
 
       svn_ra_serf__request_create(handler);
-      err = svn_ra_serf__context_run_wait(&lock_ctx->done, session, subpool);
+      err = svn_ra_serf__context_run_wait(&lock_ctx->done, session, iterpool);
 
       if (lock_func)
         new_err = lock_func(lock_baton, lock_ctx->path, TRUE, lock_ctx->lock,
-                            err, subpool);
+                            err, iterpool);
       svn_error_clear(err);
 
       SVN_ERR(new_err);
     }
 
+  svn_pool_destroy(iterpool);
+
   return SVN_NO_ERROR;
 }
 
@@ -677,45 +678,44 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
                     svn_boolean_t force,
                     svn_ra_lock_callback_t lock_func,
                     void *lock_baton,
-                    apr_pool_t *pool)
+                    apr_pool_t *scratch_pool)
 {
   svn_ra_serf__session_t *session = ra_session->priv;
   apr_hash_index_t *hi;
-  apr_pool_t *subpool;
+  apr_pool_t *iterpool;
 
-  subpool = svn_pool_create(pool);
+  iterpool = svn_pool_create(scratch_pool);
 
   /* ### TODO for issue 2263: Send all the locks over the wire at once.  This
      loop is just a temporary shim. */
-  for (hi = apr_hash_first(pool, path_tokens); hi; hi = apr_hash_next(hi))
+  for (hi = apr_hash_first(scratch_pool, path_tokens);
+       hi;
+       hi = apr_hash_next(hi))
     {
       svn_ra_serf__handler_t *handler;
       svn_ra_serf__simple_request_context_t *ctx;
       const char *req_url, *path, *token;
-      const void *key;
-      void *val;
       svn_lock_t *existing_lock = NULL;
       struct unlock_context_t unlock_ctx;
-      svn_error_t *lock_err = NULL;
+      svn_error_t *err = NULL;
+      svn_error_t *new_err = NULL;
+
 
-      svn_pool_clear(subpool);
+      svn_pool_clear(iterpool);
 
-      ctx = apr_pcalloc(subpool, sizeof(*ctx));
-      ctx->pool = subpool;
+      ctx = apr_pcalloc(iterpool, sizeof(*ctx));
+      ctx->pool = iterpool;
 
-      apr_hash_this(hi, &key, NULL, &val);
-      path = key;
-      token = val;
+      path = svn__apr_hash_index_key(hi);
+      token = svn__apr_hash_index_val(hi);
 
       if (force && (!token || token[0] == '\0'))
         {
           SVN_ERR(svn_ra_serf__get_lock(ra_session, &existing_lock, path,
-                                        subpool));
+                                        iterpool));
           token = existing_lock->token;
           if (!token)
             {
-              svn_error_t *err;
-
               err = svn_error_createf(SVN_ERR_RA_NOT_LOCKED, NULL,
                                       _("'%s' is not locked in the repository"),
                                       path);
@@ -723,22 +723,29 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
               if (lock_func)
                 {
                   svn_error_t *err2;
-                  err2 = lock_func(lock_baton, path, FALSE, NULL, err, subpool);
+                  err2 = lock_func(lock_baton, path, FALSE, NULL, err,
+                                   iterpool);
                   svn_error_clear(err);
+                  err = NULL;
                   if (err2)
-                    return err2;
+                    return svn_error_trace(err2);
+                }
+              else
+                {
+                  svn_error_clear(err);
+                  err = NULL;
                 }
               continue;
             }
         }
 
       unlock_ctx.force = force;
-      unlock_ctx.token = apr_pstrcat(subpool, "<", token, ">", (char *)NULL);
+      unlock_ctx.token = apr_pstrcat(iterpool, "<", token, ">", (char *)NULL);
 
       req_url = svn_path_url_add_component2(session->session_url.path, path,
-                                            subpool);
+                                            iterpool);
 
-      handler = apr_pcalloc(subpool, sizeof(*handler));
+      handler = apr_pcalloc(iterpool, sizeof(*handler));
 
       handler->method = "UNLOCK";
       handler->path = req_url;
@@ -752,7 +759,7 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
       handler->response_baton = ctx;
 
       svn_ra_serf__request_create(handler);
-      SVN_ERR(svn_ra_serf__context_run_wait(&ctx->done, session, subpool));
+      SVN_ERR(svn_ra_serf__context_run_wait(&ctx->done, session, iterpool));
 
       switch (ctx->status)
         {
@@ -760,23 +767,25 @@ svn_ra_serf__unlock(svn_ra_session_t *ra
             break; /* OK */
           case 403:
             /* Api users expect this specific error code to detect failures */
-            lock_err = svn_error_createf(SVN_ERR_FS_LOCK_OWNER_MISMATCH, NULL,
-                                         _("Unlock request failed: %d %s"),
-                                         ctx->status, ctx->reason);
+            err = svn_error_createf(SVN_ERR_FS_LOCK_OWNER_MISMATCH, NULL,
+                                    _("Unlock request failed: %d %s"),
+                                    ctx->status, ctx->reason);
             break;
           default:
-            lock_err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
-                                   _("Unlock request failed: %d %s"),
-                                   ctx->status, ctx->reason);
+            err = svn_error_createf(SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
+                                    _("Unlock request failed: %d %s"),
+                                    ctx->status, ctx->reason);
         }
 
       if (lock_func)
-        {
-          SVN_ERR(lock_func(lock_baton, path, FALSE, existing_lock,
-                            lock_err, subpool));
-          svn_error_clear(lock_err);
-        }
+        new_err = lock_func(lock_baton, path, FALSE, existing_lock, err,
+                            iterpool);
+
+      svn_error_clear(err);
+      SVN_ERR(new_err);
     }
 
+  svn_pool_destroy(iterpool);
+
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/ra_serf.h?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/ra_serf.h Tue Mar  6 17:50:23 2012
@@ -148,6 +148,9 @@ struct svn_ra_serf__session_t {
   svn_cancel_func_t cancel_func;
   void *cancel_baton;
 
+  /* Ev2 shim callbacks */
+  svn_delta_shim_callbacks_t *shim_callbacks;
+
   /* Error that we've received but not yet returned upstream. */
   svn_error_t *pending_error;
 
@@ -1454,6 +1457,11 @@ svn_ra_serf__error_on_status(int status_
                              const char *path,
                              const char *location);
 
+svn_error_t *
+svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *session,
+                                    svn_delta_shim_callbacks_t *callbacks);
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/serf.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/serf.c Tue Mar  6 17:50:23 2012
@@ -1157,7 +1157,8 @@ static const svn_ra__vtable_t serf_vtabl
   svn_ra_serf__replay,
   svn_ra_serf__has_capability,
   svn_ra_serf__replay_range,
-  svn_ra_serf__get_deleted_rev
+  svn_ra_serf__get_deleted_rev,
+  svn_ra_serf__register_editor_shim_callbacks
 };
 
 svn_error_t *

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/update.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/update.c Tue Mar  6 17:50:23 2012
@@ -1691,7 +1691,9 @@ start_report(svn_ra_serf__xml_parser_t *
         }
       else
         {
-          SVN_ERR_MALFUNCTION();
+          return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+                                   _("Unknown tag '%s' while at state %d"),
+                                   name.name, state);
         }
 
     }
@@ -1766,7 +1768,9 @@ start_report(svn_ra_serf__xml_parser_t *
         }
       else
         {
-          SVN_ERR_MALFUNCTION();
+          return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+                                   _("Unknown tag '%s' while at state %d"),
+                                   name.name, state);
         }
     }
   else if (state == IGNORE_PROP_NAME)

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/util.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_serf/util.c Tue Mar  6 17:50:23 2012
@@ -38,6 +38,7 @@
 #include "svn_private_config.h"
 #include "svn_string.h"
 #include "svn_xml.h"
+#include "../libsvn_ra/ra_loader.h"
 #include "private/svn_dep_compat.h"
 #include "private/svn_fspath.h"
 
@@ -2466,3 +2467,13 @@ svn_ra_serf__error_on_status(int status_
 
   return SVN_NO_ERROR;
 }
+
+svn_error_t *
+svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *ra_session,
+                                    svn_delta_shim_callbacks_t *callbacks)
+{
+  svn_ra_serf__session_t *session = ra_session->priv;
+
+  session->shim_callbacks = callbacks;
+  return SVN_NO_ERROR;
+}

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/client.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/client.c Tue Mar  6 17:50:23 2012
@@ -2496,6 +2496,18 @@ ra_svn_get_deleted_rev(svn_ra_session_t 
   return svn_ra_svn_read_cmd_response(conn, pool, "r", revision_deleted);
 }
 
+static svn_error_t *
+ra_svn_register_editor_shim_callbacks(svn_ra_session_t *session,
+                                      svn_delta_shim_callbacks_t *callbacks)
+{
+  svn_ra_svn__session_baton_t *sess_baton = session->priv;
+  svn_ra_svn_conn_t *conn = sess_baton->conn;
+
+  conn->shim_callbacks = callbacks;
+
+  return SVN_NO_ERROR;
+}
+
 
 static const svn_ra__vtable_t ra_svn_vtable = {
   svn_ra_svn_version,
@@ -2532,7 +2544,8 @@ static const svn_ra__vtable_t ra_svn_vta
   ra_svn_replay,
   ra_svn_has_capability,
   ra_svn_replay_range,
-  ra_svn_get_deleted_rev
+  ra_svn_get_deleted_rev,
+  ra_svn_register_editor_shim_callbacks
 };
 
 svn_error_t *

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/cyrus_auth.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/cyrus_auth.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/cyrus_auth.c Tue Mar  6 17:50:23 2012
@@ -125,7 +125,7 @@ static int check_result(svn_error_t *err
       svn_error_clear(err);
       return -1;
     }
-    
+
   return 0;
 }
 
@@ -180,9 +180,9 @@ svn_ra_svn__sasl_common_init(apr_pool_t 
                  sasl_mutex_free_cb);
   free_mutexes = apr_array_make(sasl_pool, 0, sizeof(svn_mutex__t *));
   return svn_mutex__init(&array_mutex, TRUE, sasl_pool);
-    
+
 #endif /* APR_HAS_THREADS */
-  
+
   return SVN_NO_ERROR;
 }
 

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/editorp.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/editorp.c Tue Mar  6 17:50:23 2012
@@ -408,8 +408,6 @@ void svn_ra_svn_get_editor(const svn_del
 {
   svn_delta_editor_t *ra_svn_editor = svn_delta_default_editor(pool);
   ra_svn_edit_baton_t *eb;
-  svn_delta_shim_callbacks_t *shim_callbacks =
-                                    svn_delta_shim_callbacks_default(pool);
 
   eb = apr_palloc(pool, sizeof(*eb));
   eb->conn = conn;
@@ -439,7 +437,7 @@ void svn_ra_svn_get_editor(const svn_del
   *edit_baton = eb;
 
   svn_error_clear(svn_editor__insert_shims(editor, edit_baton, *editor,
-                                           *edit_baton, shim_callbacks,
+                                           *edit_baton, conn->shim_callbacks,
                                            pool, pool));
 }
 

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/marshal.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/marshal.c Tue Mar  6 17:50:23 2012
@@ -125,6 +125,14 @@ svn_error_t *svn_ra_svn_set_capabilities
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_ra_svn__set_shim_callbacks(svn_ra_svn_conn_t *conn,
+                               svn_delta_shim_callbacks_t *shim_callbacks)
+{
+  conn->shim_callbacks = shim_callbacks;
+  return SVN_NO_ERROR;
+}
+
 svn_boolean_t svn_ra_svn_has_capability(svn_ra_svn_conn_t *conn,
                                         const char *capability)
 {

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/ra_svn.h
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/ra_svn.h?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/ra_svn.h (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_ra_svn/ra_svn.h Tue Mar  6 17:50:23 2012
@@ -87,6 +87,7 @@ struct svn_ra_svn_conn_st {
   apr_hash_t *capabilities;
   int compression_level;
   char *remote_ip;
+  svn_delta_shim_callbacks_t *shim_callbacks;
   apr_pool_t *pool;
 };
 

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/commit.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/commit.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/commit.c Tue Mar  6 17:50:23 2012
@@ -783,21 +783,45 @@ abort_edit(void *edit_baton,
 
 
 static svn_error_t *
-prop_fetch_func(apr_hash_t **props,
-                void *baton,
-                const char *path,
-                svn_revnum_t base_revision,
-                apr_pool_t *result_pool,
-                apr_pool_t *scratch_pool)
+rationalize_shim_path(const char **fs_path,
+                      struct edit_baton *eb,
+                      const char *path,
+                      apr_pool_t *result_pool,
+                      apr_pool_t *scratch_pool)
+{
+  if (svn_path_is_url(path))
+    {
+      /* This is a copyfrom URL. */
+      path = svn_uri_skip_ancestor(eb->repos_url, path, scratch_pool);
+      *fs_path = svn_fspath__canonicalize(path, scratch_pool);
+    }
+  else
+    {
+      /* This is a base-relative path. */
+      if (path[0] != '/')
+        /* Get an absolute path for use in the FS. */
+        *fs_path = svn_fspath__join(eb->base_path, path, scratch_pool);
+      else
+        *fs_path = path;
+    }
+
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+fetch_props_func(apr_hash_t **props,
+                 void *baton,
+                 const char *path,
+                 svn_revnum_t base_revision,
+                 apr_pool_t *result_pool,
+                 apr_pool_t *scratch_pool)
 {
   struct edit_baton *eb = baton;
   svn_fs_root_t *fs_root;
   svn_error_t *err;
 
-  if (path[0] != '/')
-    /* Get an absolute path for use in the FS. */
-    path = svn_fspath__join(eb->base_path, path, scratch_pool);
-
+  SVN_ERR(rationalize_shim_path(&path, eb, path, scratch_pool, scratch_pool));
   SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs,
                                svn_fs_txn_base_revision(eb->txn),
                                scratch_pool));
@@ -815,7 +839,7 @@ prop_fetch_func(apr_hash_t **props,
 }
 
 static svn_error_t *
-kind_fetch_func(svn_kind_t *kind,
+fetch_kind_func(svn_kind_t *kind,
                 void *baton,
                 const char *path,
                 svn_revnum_t base_revision,
@@ -828,27 +852,14 @@ kind_fetch_func(svn_kind_t *kind,
   if (!SVN_IS_VALID_REVNUM(base_revision))
     base_revision = svn_fs_txn_base_revision(eb->txn);
 
-  if (svn_path_is_url(path))
-    {
-      /* This is a copyfrom URL. */
-      path = svn_uri_skip_ancestor(eb->repos_url, path, scratch_pool);
-      path = svn_fspath__canonicalize(path, scratch_pool);
-    }
-  else
-    {
-      /* This is a base-relative path. */
-      if (path[0] != '/')
-        /* Get an absolute path for use in the FS. */
-        path = svn_fspath__join(eb->base_path, path, scratch_pool);
-    }
-
+  SVN_ERR(rationalize_shim_path(&path, eb, path, scratch_pool, scratch_pool));
   SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));
 
   SVN_ERR(svn_fs_check_path(&node_kind, fs_root, path, scratch_pool));
   *kind = svn__kind_from_node_kind(node_kind, FALSE);
 
   return SVN_NO_ERROR;
-} 
+}
 
 static svn_error_t *
 fetch_base_func(const char **filename,
@@ -868,20 +879,7 @@ fetch_base_func(const char **filename,
   if (!SVN_IS_VALID_REVNUM(base_revision))
     base_revision = svn_fs_txn_base_revision(eb->txn);
 
-  if (svn_path_is_url(path))
-    {
-      /* This is a copyfrom URL. */
-      path = svn_uri_skip_ancestor(eb->repos_url, path, scratch_pool);
-      path = svn_fspath__canonicalize(path, scratch_pool);
-    }
-  else
-    {
-      /* This is a base-relative path. */
-      if (path[0] != '/')
-        /* Get an absolute path for use in the FS. */
-        path = svn_fspath__join(eb->base_path, path, scratch_pool);
-    }
-
+  SVN_ERR(rationalize_shim_path(&path, eb, path, scratch_pool, scratch_pool));
   SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));
 
   err = svn_fs_file_contents(&contents, fs_root, path, scratch_pool);
@@ -977,8 +975,8 @@ svn_repos_get_commit_editor5(const svn_d
   *edit_baton = eb;
   *editor = e;
 
-  shim_callbacks->fetch_props_func = prop_fetch_func;
-  shim_callbacks->fetch_kind_func = kind_fetch_func;
+  shim_callbacks->fetch_props_func = fetch_props_func;
+  shim_callbacks->fetch_kind_func = fetch_kind_func;
   shim_callbacks->fetch_base_func = fetch_base_func;
   shim_callbacks->fetch_baton = eb;
 

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/dump.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/dump.c Tue Mar  6 17:50:23 2012
@@ -864,8 +864,14 @@ fetch_props_func(apr_hash_t **props,
 {
   struct edit_baton *eb = baton;
   svn_error_t *err;
+  svn_fs_root_t *fs_root;
+
+  if (!SVN_IS_VALID_REVNUM(base_revision))
+    base_revision = eb->current_rev - 1;
 
-  err = svn_fs_node_proplist(props, eb->fs_root, path, result_pool);
+  SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));
+
+  err = svn_fs_node_proplist(props, fs_root, path, result_pool);
   if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
     {
       svn_error_clear(err);
@@ -890,10 +896,9 @@ fetch_kind_func(svn_kind_t *kind,
   svn_fs_root_t *fs_root;
 
   if (!SVN_IS_VALID_REVNUM(base_revision))
-    fs_root = eb->fs_root;
-  else
-    SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision,
-                                 scratch_pool));
+    base_revision = eb->current_rev - 1;
+
+  SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));
 
   SVN_ERR(svn_fs_check_path(&node_kind, fs_root, path, scratch_pool));
   *kind = svn__kind_from_node_kind(node_kind, FALSE);
@@ -917,10 +922,9 @@ fetch_base_func(const char **filename,
   svn_fs_root_t *fs_root;
 
   if (!SVN_IS_VALID_REVNUM(base_revision))
-    fs_root = eb->fs_root;
-  else
-    SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision,
-                                 scratch_pool));
+    base_revision = eb->current_rev - 1;
+
+  SVN_ERR(svn_fs_revision_root(&fs_root, eb->fs, base_revision, scratch_pool));
 
   err = svn_fs_file_contents(&contents, fs_root, path, scratch_pool);
   if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND)
@@ -1391,10 +1395,9 @@ svn_repos_verify_fs2(svn_repos_t *repos,
                                "(youngest revision is %ld)"),
                              end_rev, youngest);
 
-  /* Verify global/auxiliary data before verifying revisions. */
-  if (start_rev == 0)
-    SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), cancel_func, cancel_baton,
-                          pool));
+  /* Verify global/auxiliary data and backend-specific data first. */
+  SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), cancel_func, cancel_baton,
+                        start_rev, end_rev, pool));
 
   /* Create a notify object that we can reuse within the loop. */
   if (notify_func)
@@ -1415,7 +1418,7 @@ svn_repos_verify_fs2(svn_repos_t *repos,
       /* Get cancellable dump editor, but with our close_directory handler. */
       SVN_ERR(get_dump_editor((const svn_delta_editor_t **)&dump_editor,
                               &dump_edit_baton, fs, rev, "",
-                              svn_stream_empty(pool),
+                              svn_stream_empty(iterpool),
                               NULL, NULL,
                               verify_close_directory,
                               notify_func, notify_baton,
@@ -1432,6 +1435,10 @@ svn_repos_verify_fs2(svn_repos_t *repos,
       SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,
                                 cancel_editor, cancel_edit_baton,
                                 NULL, NULL, iterpool));
+      /* While our editor close_edit implementation is a no-op, we still
+         do this for completeness. */
+      SVN_ERR(cancel_editor->close_edit(cancel_edit_baton, iterpool));
+
       SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, iterpool));
 
       if (notify_func)

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/fs-wrap.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/fs-wrap.c Tue Mar  6 17:50:23 2012
@@ -61,7 +61,7 @@ svn_repos_fs_commit_txn(const char **con
     return err;
 
   /* Run post-commit hooks. */
-  if ((err2 = svn_repos__hooks_post_commit(repos, *new_rev, pool)))
+  if ((err2 = svn_repos__hooks_post_commit(repos, *new_rev, txn_name, pool)))
     {
       err2 = svn_error_create
                (SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED, err2,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/hooks.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/hooks.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/hooks.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/hooks.c Tue Mar  6 17:50:23 2012
@@ -159,6 +159,37 @@ check_hook_result(const char *name, cons
                           failure_message->data);
 }
 
+/* Copy the environment given as key/value pairs of ENV_HASH into
+ * an array of C strings allocated in RESULT_POOL.
+ * If the hook environment is empty, return NULL.
+ * Use SCRATCH_POOL for temporary allocations. */
+static const char **
+env_from_env_hash(apr_hash_t *env_hash,
+                  apr_pool_t *result_pool,
+                  apr_pool_t *scratch_pool)
+{
+  apr_hash_index_t *hi;
+  const char **env;
+  const char **envp;
+
+  if (!env_hash || apr_hash_count(env_hash) == 0)
+    return NULL;
+
+  env = apr_palloc(result_pool,
+                   sizeof(const char *) * (apr_hash_count(env_hash) + 1));
+  envp = env;
+  for (hi = apr_hash_first(scratch_pool, env_hash); hi; hi = apr_hash_next(hi))
+    {
+      *envp = apr_psprintf(result_pool, "%s=%s",
+                           (const char *)svn__apr_hash_index_key(hi),
+                           (const char *)svn__apr_hash_index_val(hi));
+      envp++;
+    }
+  *envp = NULL;
+
+  return env;
+}
+
 /* NAME, CMD and ARGS are the name, path to and arguments for the hook
    program that is to be run.  The hook's exit status will be checked,
    and if an error occurred the hook's stderr output will be added to
@@ -174,6 +205,7 @@ run_hook_cmd(svn_string_t **result,
              const char *name,
              const char *cmd,
              const char **args,
+             apr_hash_t *hooks_env,
              apr_file_t *stdin_handle,
              apr_pool_t *pool)
 {
@@ -196,9 +228,10 @@ run_hook_cmd(svn_string_t **result,
             (apr_err, _("Can't create null stdout for hook '%s'"), cmd);
     }
 
-  err = svn_io_start_cmd2(&cmd_proc, ".", cmd, args, FALSE,
-                          FALSE, stdin_handle, result != NULL, null_handle,
-                          TRUE, NULL, pool);
+  err = svn_io_start_cmd3(&cmd_proc, ".", cmd, args,
+                          env_from_env_hash(hooks_env, pool, pool),
+                          FALSE, FALSE, stdin_handle, result != NULL,
+                          null_handle, TRUE, NULL, pool);
 
   if (err)
     {
@@ -358,8 +391,8 @@ svn_repos__hooks_start_commit(svn_repos_
       args[3] = capabilities_string;
       args[4] = NULL;
 
-      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_START_COMMIT, hook, args, NULL,
-                           pool));
+      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_START_COMMIT, hook, args,
+                           repos->hooks_env, NULL, pool));
     }
 
   return SVN_NO_ERROR;
@@ -438,7 +471,7 @@ svn_repos__hooks_pre_commit(svn_repos_t 
                                  APR_READ, APR_OS_DEFAULT, pool));
 
       SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_PRE_COMMIT, hook, args,
-                           stdin_handle, pool));
+                           repos->hooks_env, stdin_handle, pool));
     }
 
   return SVN_NO_ERROR;
@@ -448,6 +481,7 @@ svn_repos__hooks_pre_commit(svn_repos_t 
 svn_error_t  *
 svn_repos__hooks_post_commit(svn_repos_t *repos,
                              svn_revnum_t rev,
+                             const char *txn_name,
                              apr_pool_t *pool)
 {
   const char *hook = svn_repos_post_commit_hook(repos, pool);
@@ -459,15 +493,16 @@ svn_repos__hooks_post_commit(svn_repos_t
     }
   else if (hook)
     {
-      const char *args[4];
+      const char *args[5];
 
       args[0] = hook;
       args[1] = svn_dirent_local_style(svn_repos_path(repos, pool), pool);
       args[2] = apr_psprintf(pool, "%ld", rev);
-      args[3] = NULL;
+      args[3] = txn_name;
+      args[4] = NULL;
 
-      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_POST_COMMIT, hook, args, NULL,
-                           pool));
+      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_POST_COMMIT, hook, args,
+                           repos->hooks_env, NULL, pool));
     }
 
   return SVN_NO_ERROR;
@@ -514,8 +549,8 @@ svn_repos__hooks_pre_revprop_change(svn_
       args[5] = action_string;
       args[6] = NULL;
 
-      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_PRE_REVPROP_CHANGE, hook, args,
-                           stdin_handle, pool));
+      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_PRE_REVPROP_CHANGE, hook,
+                           args, repos->hooks_env, stdin_handle, pool));
 
       SVN_ERR(svn_io_file_close(stdin_handle, pool));
     }
@@ -577,7 +612,7 @@ svn_repos__hooks_post_revprop_change(svn
       args[6] = NULL;
 
       SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_POST_REVPROP_CHANGE, hook,
-                           args, stdin_handle, pool));
+                           args, repos->hooks_env, stdin_handle, pool));
 
       SVN_ERR(svn_io_file_close(stdin_handle, pool));
     }
@@ -615,8 +650,8 @@ svn_repos__hooks_pre_lock(svn_repos_t *r
       args[5] = steal_lock ? "1" : "0";
       args[6] = NULL;
 
-      SVN_ERR(run_hook_cmd(&buf, SVN_REPOS__HOOK_PRE_LOCK, hook, args, NULL,
-                           pool));
+      SVN_ERR(run_hook_cmd(&buf, SVN_REPOS__HOOK_PRE_LOCK, hook, args,
+                           repos->hooks_env, NULL, pool));
 
       if (token)
         /* No validation here; the FS will take care of that. */
@@ -660,7 +695,7 @@ svn_repos__hooks_post_lock(svn_repos_t *
       args[4] = NULL;
 
       SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_POST_LOCK, hook, args,
-                           stdin_handle, pool));
+                           repos->hooks_env, stdin_handle, pool));
 
       SVN_ERR(svn_io_file_close(stdin_handle, pool));
     }
@@ -696,8 +731,8 @@ svn_repos__hooks_pre_unlock(svn_repos_t 
       args[5] = break_lock ? "1" : "0";
       args[6] = NULL;
 
-      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_PRE_UNLOCK, hook, args, NULL,
-                           pool));
+      SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_PRE_UNLOCK, hook, args,
+                           repos->hooks_env, NULL, pool));
     }
 
   return SVN_NO_ERROR;
@@ -734,7 +769,7 @@ svn_repos__hooks_post_unlock(svn_repos_t
       args[4] = NULL;
 
       SVN_ERR(run_hook_cmd(NULL, SVN_REPOS__HOOK_POST_UNLOCK, hook, args,
-                           stdin_handle, pool));
+                           repos->hooks_env, stdin_handle, pool));
 
       SVN_ERR(svn_io_file_close(stdin_handle, pool));
     }

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/load-fs-vtable.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/load-fs-vtable.c Tue Mar  6 17:50:23 2012
@@ -487,7 +487,7 @@ new_revision_record(void **revision_bato
      several separate operations. It is highly susceptible to race conditions.
      Calculate the revision 'offset' for finding copyfrom sources.
      It might be positive or negative. */
-  rb->rev_offset = (apr_int32_t) (rb->rev) - (head_rev + 1);
+  rb->rev_offset = (apr_int32_t) ((rb->rev) - (head_rev + 1));
 
   if ((rb->rev > 0) && (! rb->skipped))
     {
@@ -506,7 +506,7 @@ new_revision_record(void **revision_bato
       if (!SVN_IS_VALID_REVNUM(pb->oldest_old_rev))
         pb->oldest_old_rev = rb->rev;
     }
-  
+
   /* If we're skipping this revision, try to notify someone. */
   if (rb->skipped && pb->notify_func)
     {
@@ -900,19 +900,28 @@ close_revision(void *baton)
   const char *conflict_msg = NULL;
   svn_revnum_t committed_rev;
   svn_error_t *err;
+  const char *txn_name;
 
   /* If we're skipping this revision or it has an invalid revision
      number, we're done here. */
   if (rb->skipped || (rb->rev <= 0))
     return SVN_NO_ERROR;
 
+  /* Get the txn name, if it will be needed. */
+  if (pb->use_pre_commit_hook || pb->use_post_commit_hook)
+    {
+      err = svn_fs_txn_name(&txn_name, rb->txn, rb->pool);
+      if (err)
+        {
+          svn_error_clear(svn_fs_abort_txn(rb->txn, rb->pool));
+          return svn_error_trace(err);
+        }
+    }
+
   /* Run the pre-commit hook, if so commanded. */
   if (pb->use_pre_commit_hook)
     {
-      const char *txn_name;
-      err = svn_fs_txn_name(&txn_name, rb->txn, rb->pool);
-      if (! err)
-        err = svn_repos__hooks_pre_commit(pb->repos, txn_name, rb->pool);
+      err = svn_repos__hooks_pre_commit(pb->repos, txn_name, rb->pool);
       if (err)
         {
           svn_error_clear(svn_fs_abort_txn(rb->txn, rb->pool));
@@ -945,7 +954,7 @@ close_revision(void *baton)
   if (pb->use_post_commit_hook)
     {
       if ((err = svn_repos__hooks_post_commit(pb->repos, committed_rev,
-                                              rb->pool)))
+                                              txn_name, rb->pool)))
         return svn_error_create
           (SVN_ERR_REPOS_POST_COMMIT_HOOK_FAILED, err,
            _("Commit succeeded, but post-commit hook failed"));

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/log.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/log.c Tue Mar  6 17:50:23 2012
@@ -264,6 +264,43 @@ detect_changed(apr_hash_t **changed,
                                              : svn_tristate_false;
       item->props_modified = change->prop_mod ? svn_tristate_true
                                               : svn_tristate_false;
+
+      /* Pre-1.6 revision files don't store the change path kind, so fetch
+         it manually. */
+      if (item->node_kind == svn_node_unknown)
+        {
+          svn_fs_root_t *check_root = root;
+          const char *check_path = path;
+
+          /* Deleted items don't exist so check earlier revision.  We
+             know the parent must exist and could be a copy */
+          if (change->change_kind == svn_fs_path_change_delete)
+            {
+              svn_fs_history_t *history;
+              svn_revnum_t prev_rev;
+              const char *parent_path, *name;
+
+              svn_fspath__split(&parent_path, &name, path, subpool);
+
+              SVN_ERR(svn_fs_node_history(&history, root, parent_path,
+                                          subpool));
+
+              /* Two calls because the first call returns the original
+                 revision as the deleted child means it is 'interesting' */
+              SVN_ERR(svn_fs_history_prev(&history, history, TRUE, subpool));
+              SVN_ERR(svn_fs_history_prev(&history, history, TRUE, subpool));
+
+              SVN_ERR(svn_fs_history_location(&parent_path, &prev_rev, history,
+                                              subpool));
+              SVN_ERR(svn_fs_revision_root(&check_root, fs, prev_rev, subpool));
+              check_path = svn_fspath__join(parent_path, name, subpool);
+            }
+
+          SVN_ERR(svn_fs_check_path(&item->node_kind, check_root, check_path,
+                                    subpool));
+        }
+
+
       if ((action == 'A') || (action == 'R'))
         {
           const char *copyfrom_path;
@@ -1115,7 +1152,6 @@ send_log(svn_revnum_t rev,
       && log_target_history_as_mergeinfo
       && apr_hash_count(log_target_history_as_mergeinfo))
     {
-      svn_boolean_t path_is_in_history = FALSE;
       apr_hash_index_t *hi;
       apr_pool_t *subpool = svn_pool_create(pool);
 
@@ -1128,10 +1164,12 @@ send_log(svn_revnum_t rev,
            hi;
            hi = apr_hash_next(hi))
         {
+          svn_boolean_t path_is_in_history = FALSE;
           const char *changed_path = svn__apr_hash_index_key(hi);
           apr_hash_index_t *hi2;
           apr_pool_t *inner_subpool = svn_pool_create(subpool);
 
+          /* Look at each path on the log target's mergeinfo. */
           for (hi2 = apr_hash_first(inner_subpool,
                                     log_target_history_as_mergeinfo);
                hi2;
@@ -1142,6 +1180,8 @@ send_log(svn_revnum_t rev,
               apr_array_header_t *rangelist =
                 svn__apr_hash_index_val(hi2);
 
+              /* Check whether CHANGED_PATH at revision REV is a child of
+                 a (path, revision) tuple in LOG_TARGET_HISTORY_AS_MERGEINFO. */
               if (svn_fspath__skip_ancestor(mergeinfo_path, changed_path))
                 {
                   int i;
@@ -1771,7 +1811,7 @@ store_search(svn_mergeinfo_t processed,
                                                   sizeof(svn_merge_range_t*));
       svn_merge_range_t *range = apr_palloc(processed_pool,
                                             sizeof(svn_merge_range_t));
-      
+
       range->start = start;
       range->end = end;
       range->inheritable = TRUE;
@@ -2228,17 +2268,40 @@ svn_repos_get_logs4(svn_repos_t *repos,
       int i;
       apr_pool_t *iterpool = svn_pool_create(pool);
 
+      /* If we are provided an authz callback function, use it to
+         verify that the user has read access to the root path in the
+         first of our revisions.
+
+         ### FIXME:  Strictly speaking, we should be checking this
+         ### access in every revision along the line.  But currently,
+         ### there are no known authz implementations which concern
+         ### themselves with per-revision access.  */
+      if (authz_read_func)
+        {
+          svn_boolean_t readable;
+          svn_fs_root_t *rev_root;
+
+          SVN_ERR(svn_fs_revision_root(&rev_root, fs,
+                                       descending_order ? end : start, pool));
+          SVN_ERR(authz_read_func(&readable, rev_root, "",
+                                  authz_read_baton, pool));
+          if (! readable)
+            return svn_error_create(SVN_ERR_AUTHZ_UNREADABLE, NULL, NULL);
+        }
+
       send_count = end - start + 1;
       if (limit && send_count > limit)
         send_count = limit;
       for (i = 0; i < send_count; ++i)
         {
-          svn_revnum_t rev = start + i;
+          svn_revnum_t rev;
 
           svn_pool_clear(iterpool);
 
           if (descending_order)
             rev = end - i;
+          else
+            rev = start + i;
           SVN_ERR(send_log(rev, fs, NULL, NULL, discover_changed_paths, FALSE,
                            FALSE, revprops, FALSE, receiver,
                            receiver_baton, authz_read_func,

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/replay.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/replay.c Tue Mar  6 17:50:23 2012
@@ -352,6 +352,116 @@ is_within_base_path(const char *path, co
   return FALSE;
 }
 
+/* Given PATH deleted under ROOT, return in READABLE whether the path was
+   readable prior to the deletion.  Consult COPIES (a stack of 'struct
+   copy_info') and AUTHZ_READ_FUNC. */
+static svn_error_t *
+was_readable(svn_boolean_t *readable,
+             svn_fs_root_t *root,
+             const char *path,
+             apr_array_header_t *copies,
+             svn_repos_authz_func_t authz_read_func,
+             void *authz_read_baton,
+             apr_pool_t *result_pool,
+             apr_pool_t *scratch_pool)
+{
+  svn_fs_root_t *inquire_root;
+  const char *inquire_path;
+  struct copy_info *info = NULL;
+  const char *relpath;
+
+  /* Short circuit. */
+  if (! authz_read_func)
+    {
+      *readable = TRUE;
+      return SVN_NO_ERROR;
+    }
+
+  if (copies->nelts != 0)
+    info = APR_ARRAY_IDX(copies, copies->nelts - 1, struct copy_info *);
+
+  /* Are we under a copy? */
+  if (info && (relpath = svn_relpath_skip_ancestor(info->path, path)))
+    {
+      SVN_ERR(svn_fs_revision_root(&inquire_root, svn_fs_root_fs(root),
+                                   info->copyfrom_rev, scratch_pool));
+      inquire_path = svn_fspath__join(info->copyfrom_path, relpath,
+                                      scratch_pool);
+    }
+  else
+    {
+      /* Compute the revision that ROOT is based on.  (Note that ROOT is not
+         r0's root, since this function is only called for deletions.)
+         ### Need a more succinct way to express this */
+      svn_revnum_t inquire_rev = SVN_INVALID_REVNUM;
+      if (svn_fs_is_txn_root(root))
+        inquire_rev = svn_fs_txn_root_base_revision(root);
+      if (svn_fs_is_revision_root(root))
+        inquire_rev =  svn_fs_revision_root_revision(root)-1;
+      SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(inquire_rev));
+
+      SVN_ERR(svn_fs_revision_root(&inquire_root, svn_fs_root_fs(root),
+                                   inquire_rev, scratch_pool));
+      inquire_path = path;
+    }
+
+  SVN_ERR(authz_read_func(readable, inquire_root, inquire_path,
+                          authz_read_baton, result_pool));
+
+  return SVN_NO_ERROR;
+}
+
+/* Initialize COPYFROM_ROOT, COPYFROM_PATH, and COPYFROM_REV with the
+   revision root, fspath, and revnum of the copyfrom of CHANGE, which
+   corresponds to PATH under ROOT.  If the copyfrom info is valid
+   (i.e., is not (NULL, SVN_INVALID_REVNUM)), then initialize SRC_READABLE
+   too, consulting AUTHZ_READ_FUNC and AUTHZ_READ_BATON if provided. */
+static svn_error_t *
+fill_copyfrom(svn_fs_root_t **copyfrom_root,
+              const char **copyfrom_path,
+              svn_revnum_t *copyfrom_rev,
+              svn_boolean_t *src_readable,
+              svn_fs_root_t *root,
+              svn_fs_path_change2_t *change,
+              svn_repos_authz_func_t authz_read_func,
+              void *authz_read_baton,
+              const char *path,
+              apr_pool_t *result_pool,
+              apr_pool_t *scratch_pool)
+{
+  if (! change->copyfrom_known)
+    {
+      SVN_ERR(svn_fs_copied_from(&(change->copyfrom_rev),
+                                 &(change->copyfrom_path),
+                                 root, path, result_pool));
+      change->copyfrom_known = TRUE;
+    }
+  *copyfrom_rev = change->copyfrom_rev;
+  *copyfrom_path = change->copyfrom_path;
+
+  if (*copyfrom_path && SVN_IS_VALID_REVNUM(*copyfrom_rev))
+    {
+      SVN_ERR(svn_fs_revision_root(copyfrom_root,
+                                   svn_fs_root_fs(root),
+                                   *copyfrom_rev, result_pool));
+
+      if (authz_read_func)
+        {
+          SVN_ERR(authz_read_func(src_readable, *copyfrom_root,
+                                  *copyfrom_path,
+                                  authz_read_baton, result_pool));
+        }
+      else
+        *src_readable = TRUE;
+    }
+  else
+    {
+      *copyfrom_root = NULL;
+      /* SRC_READABLE left uninitialized */
+    }
+  return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 path_driver_cb_func(void **dir_baton,
                     void *parent_baton,
@@ -368,7 +478,6 @@ path_driver_cb_func(void **dir_baton,
   void *file_baton = NULL;
   svn_revnum_t copyfrom_rev;
   const char *copyfrom_path;
-  svn_boolean_t src_readable = TRUE;
   svn_fs_root_t *source_root = cb->compare_root;
   const char *source_fspath = NULL;
   const char *base_path = cb->base_path;
@@ -384,9 +493,9 @@ path_driver_cb_func(void **dir_baton,
   while (cb->copies->nelts > 0
          && ! svn_dirent_is_ancestor(APR_ARRAY_IDX(cb->copies,
                                                    cb->copies->nelts - 1,
-                                                   struct copy_info).path,
+                                                   struct copy_info *)->path,
                                      edit_path))
-    cb->copies->nelts--;
+    apr_array_pop(cb->copies);
 
   change = apr_hash_get(cb->changed_paths, edit_path, APR_HASH_KEY_STRING);
   if (! change)
@@ -419,8 +528,18 @@ path_driver_cb_func(void **dir_baton,
 
   /* Handle any deletions. */
   if (do_delete)
-    SVN_ERR(editor->delete_entry(edit_path, SVN_INVALID_REVNUM,
-                                 parent_baton, pool));
+    {
+      svn_boolean_t readable;
+
+      /* Issue #4121: delete under under a copy, of a path that was unreadable
+         at its pre-copy location. */
+      SVN_ERR(was_readable(&readable, root, edit_path, cb->copies,
+                            cb->authz_read_func, cb->authz_read_baton,
+                            pool, pool));
+      if (readable)
+        SVN_ERR(editor->delete_entry(edit_path, SVN_INVALID_REVNUM,
+                                     parent_baton, pool));
+    }
 
   /* Fetch the node kind if it makes sense to do so. */
   if (! do_delete || do_add)
@@ -437,31 +556,14 @@ path_driver_cb_func(void **dir_baton,
   /* Handle any adds/opens. */
   if (do_add)
     {
-      svn_fs_root_t *copyfrom_root = NULL;
-      /* Was this node copied? */
-      if (! change->copyfrom_known)
-        {
-          SVN_ERR(svn_fs_copied_from(&(change->copyfrom_rev),
-                                     &(change->copyfrom_path),
-                                     root, edit_path, pool));
-          change->copyfrom_known = TRUE;
-        }
-      copyfrom_rev = change->copyfrom_rev;
-      copyfrom_path = change->copyfrom_path;
+      svn_boolean_t src_readable;
+      svn_fs_root_t *copyfrom_root;
 
-      if (copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_rev))
-        {
-          SVN_ERR(svn_fs_revision_root(&copyfrom_root,
-                                       svn_fs_root_fs(root),
-                                       copyfrom_rev, pool));
-
-          if (cb->authz_read_func)
-            {
-              SVN_ERR(cb->authz_read_func(&src_readable, copyfrom_root,
-                                          copyfrom_path,
-                                          cb->authz_read_baton, pool));
-            }
-        }
+      /* Was this node copied? */
+      SVN_ERR(fill_copyfrom(&copyfrom_root, &copyfrom_path, &copyfrom_rev,
+                            &src_readable, root, change,
+                            cb->authz_read_func, cb->authz_read_baton,
+                            edit_path, pool, pool));
 
       /* If we have a copyfrom path, and we can't read it or we're just
          ignoring it, or the copyfrom rev is prior to the low water mark
@@ -511,11 +613,13 @@ path_driver_cb_func(void **dir_baton,
              (possibly nested) copy operation. */
           if (change->node_kind == svn_node_dir)
             {
-              struct copy_info *info = &APR_ARRAY_PUSH(cb->copies,
-                                                       struct copy_info);
+              struct copy_info *info = apr_pcalloc(cb->pool, sizeof(*info));
+
               info->path = apr_pstrdup(cb->pool, edit_path);
               info->copyfrom_path = apr_pstrdup(cb->pool, copyfrom_path);
               info->copyfrom_rev = copyfrom_rev;
+
+              APR_ARRAY_PUSH(cb->copies, struct copy_info *) = info;
             }
 
           /* Save the source so that we can use it later, when we
@@ -531,11 +635,13 @@ path_driver_cb_func(void **dir_baton,
              past... */
           if (change->node_kind == svn_node_dir && cb->copies->nelts > 0)
             {
-              struct copy_info *info = &APR_ARRAY_PUSH(cb->copies,
-                                                       struct copy_info);
+              struct copy_info *info = apr_pcalloc(cb->pool, sizeof(*info));
+
               info->path = apr_pstrdup(cb->pool, edit_path);
               info->copyfrom_path = NULL;
               info->copyfrom_rev = SVN_INVALID_REVNUM;
+
+              APR_ARRAY_PUSH(cb->copies, struct copy_info *) = info;
             }
           source_root = NULL;
           source_fspath = NULL;
@@ -568,9 +674,9 @@ path_driver_cb_func(void **dir_baton,
          delta source. */
       if (cb->copies->nelts > 0)
         {
-          struct copy_info *info = &APR_ARRAY_IDX(cb->copies,
-                                                  cb->copies->nelts - 1,
-                                                  struct copy_info);
+          struct copy_info *info = APR_ARRAY_IDX(cb->copies,
+                                                 cb->copies->nelts - 1,
+                                                 struct copy_info *);
           if (info->copyfrom_path)
             {
               const char *relpath = svn_relpath_skip_ancestor(info->path,
@@ -597,45 +703,31 @@ path_driver_cb_func(void **dir_baton,
     {
       if (change->prop_mod)
         {
-          if (cb->compare_root)
-            {
-              apr_array_header_t *prop_diffs;
-              apr_hash_t *old_props;
-              apr_hash_t *new_props;
-              int i;
-
-              if (source_root)
-                SVN_ERR(svn_fs_node_proplist(&old_props, source_root,
-                                             source_fspath, pool));
-              else
-                old_props = apr_hash_make(pool);
-
-              SVN_ERR(svn_fs_node_proplist(&new_props, root, edit_path, pool));
-
-              SVN_ERR(svn_prop_diffs(&prop_diffs, new_props, old_props,
-                                     pool));
-
-              for (i = 0; i < prop_diffs->nelts; ++i)
-                {
-                  svn_prop_t *pc = &APR_ARRAY_IDX(prop_diffs, i, svn_prop_t);
-                   if (change->node_kind == svn_node_dir)
-                     SVN_ERR(editor->change_dir_prop(*dir_baton, pc->name,
-                                                     pc->value, pool));
-                   else if (change->node_kind == svn_node_file)
-                     SVN_ERR(editor->change_file_prop(file_baton, pc->name,
-                                                      pc->value, pool));
-                }
-            }
+          apr_array_header_t *prop_diffs;
+          apr_hash_t *old_props;
+          apr_hash_t *new_props;
+          int i;
+
+          if (source_root)
+            SVN_ERR(svn_fs_node_proplist(&old_props, source_root,
+                                         source_fspath, pool));
           else
+            old_props = apr_hash_make(pool);
+
+          SVN_ERR(svn_fs_node_proplist(&new_props, root, edit_path, pool));
+
+          SVN_ERR(svn_prop_diffs(&prop_diffs, new_props, old_props,
+                                 pool));
+
+          for (i = 0; i < prop_diffs->nelts; ++i)
             {
-              /* Just do a dummy prop change to signal that there are *any*
-                 propmods. */
-              if (change->node_kind == svn_node_dir)
-                SVN_ERR(editor->change_dir_prop(*dir_baton, "", NULL,
-                                                pool));
-              else if (change->node_kind == svn_node_file)
-                SVN_ERR(editor->change_file_prop(file_baton, "", NULL,
-                                                 pool));
+              svn_prop_t *pc = &APR_ARRAY_IDX(prop_diffs, i, svn_prop_t);
+               if (change->node_kind == svn_node_dir)
+                 SVN_ERR(editor->change_dir_prop(*dir_baton, pc->name,
+                                                 pc->value, pool));
+               else if (change->node_kind == svn_node_file)
+                 SVN_ERR(editor->change_file_prop(file_baton, pc->name,
+                                                  pc->value, pool));
             }
         }
 
@@ -806,7 +898,7 @@ svn_repos_replay2(svn_fs_root_t *root,
                                    pool));
     }
 
-  cb_baton.copies = apr_array_make(pool, 4, sizeof(struct copy_info));
+  cb_baton.copies = apr_array_make(pool, 4, sizeof(struct copy_info *));
   cb_baton.pool = pool;
 
   /* Determine the revision to use throughout the edit, and call

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/reporter.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/reporter.c Tue Mar  6 17:50:23 2012
@@ -898,6 +898,21 @@ update_entry(report_baton_t *b, svn_revn
       SVN_ERR(svn_repos_deleted_rev(svn_fs_root_fs(b->t_root), t_path,
                                     s_rev, b->t_rev, &deleted_rev,
                                     pool));
+
+      if (!SVN_IS_VALID_REVNUM(deleted_rev))
+        {
+          /* Two possibilities: either the thing doesn't exist in S_REV; or
+             it wasn't deleted between S_REV and B->T_REV.  In the first case,
+             I think we should leave DELETED_REV as SVN_INVALID_REVNUM, but
+             in the second, it should be set to B->T_REV-1 for the call to
+             delete_entry() below. */
+          svn_node_kind_t kind;
+
+          SVN_ERR(svn_fs_check_path(&kind, b->t_root, t_path, pool));
+          if (kind != svn_node_none)
+            deleted_rev = b->t_rev - 1;
+        }
+
       SVN_ERR(b->editor->delete_entry(e_path, deleted_rev, dir_baton,
                                       pool));
       s_path = NULL;

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/repos.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/repos.c Tue Mar  6 17:50:23 2012
@@ -165,6 +165,12 @@ svn_repos_post_revprop_change_hook(svn_r
                        pool);
 }
 
+void
+svn_repos_hooks_setenv(svn_repos_t *repos,
+                       apr_hash_t *hooks_env)
+{
+  repos->hooks_env = hooks_env;
+}
 
 static svn_error_t *
 create_repos_dir(const char *path, apr_pool_t *pool)
@@ -736,6 +742,7 @@ PREWRITTEN_HOOKS_TEXT
 "#"                                                                          NL
 "#   [1] REPOS-PATH   (the path to this repository)"                         NL
 "#   [2] REV          (the number of the revision just committed)"           NL
+"#   [3] TXN-NAME     (the name of the transaction that has become REV)"     NL
 "#"                                                                          NL
 "# The default working directory for the invocation is undefined, so"        NL
 "# the program should set one explicitly if it cares."                       NL
@@ -765,6 +772,7 @@ PREWRITTEN_HOOKS_TEXT
 ""                                                                           NL
 "REPOS=\"$1\""                                                               NL
 "REV=\"$2\""                                                                 NL
+"TXN_NAME=\"$3\""                                                            NL
                                                                              NL
 "mailer.py commit \"$REPOS\" \"$REV\" /path/to/mailer.conf"                  NL;
 
@@ -1040,7 +1048,17 @@ create_conf(svn_repos_t *repos, apr_pool
 "### to the effective key length for encryption (e.g. 128 means 128-bit"     NL
 "### encryption). The values below are the defaults."                        NL
 "# min-encryption = 0"                                                       NL
-"# max-encryption = 256"                                                     NL;
+"# max-encryption = 256"                                                     NL
+""                                                                           NL
+"[hooks-env]"                                                                NL
+"### Options in this section define environment variables for use by"        NL
+"### hook scripts run by svnserve."                                          NL
+#ifdef WIN32
+"# PATH = C:\\Program Files\\Subversion\\bin"                                NL
+#else
+"# PATH = /bin:/sbin:/usr/bin:/usr/sbin"                                     NL
+#endif
+"# LC_CTYPE = en_US.UTF-8"                                                   NL;
 
     SVN_ERR_W(svn_io_file_create(svn_repos_svnserve_conf(repos, pool),
                                  svnserve_conf_contents, pool),

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/repos.h?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/repos.h (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/repos.h Tue Mar  6 17:50:23 2012
@@ -140,6 +140,10 @@ struct svn_repos_t
      sufficiently well-informed internal code may just compare against
      those constants' addresses, therefore). */
   apr_hash_t *repository_capabilities;
+
+  /* The environment inherited to hook scripts. If NULL, hooks run
+   * in an empty environment. */
+  apr_hash_t *hooks_env;
 };
 
 
@@ -175,6 +179,7 @@ svn_repos__hooks_pre_commit(svn_repos_t 
 svn_error_t *
 svn_repos__hooks_post_commit(svn_repos_t *repos,
                              svn_revnum_t rev,
+                             const char *txn_name,
                              apr_pool_t *pool);
 
 /* Run the pre-revprop-change hook for REPOS.  Use POOL for any

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/rev_hunt.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_repos/rev_hunt.c Tue Mar  6 17:50:23 2012
@@ -154,6 +154,8 @@ svn_repos_get_committed_info(svn_revnum_
                              const char *path,
                              apr_pool_t *pool)
 {
+  apr_hash_t *revprops;
+  
   svn_fs_t *fs = svn_fs_root_fs(root);
 
   /* ### It might be simpler just to declare that revision
@@ -164,13 +166,16 @@ svn_repos_get_committed_info(svn_revnum_
   /* Get the CR field out of the node's skel. */
   SVN_ERR(svn_fs_node_created_rev(committed_rev, root, path, pool));
 
-  /* Get the date property of this revision. */
-  SVN_ERR(svn_fs_revision_prop(&committed_date_s, fs, *committed_rev,
-                               SVN_PROP_REVISION_DATE, pool));
-
-  /* Get the author property of this revision. */
-  SVN_ERR(svn_fs_revision_prop(&last_author_s, fs, *committed_rev,
-                               SVN_PROP_REVISION_AUTHOR, pool));
+  /* Get the revision properties of this revision. */
+  SVN_ERR(svn_fs_revision_proplist(&revprops, fs, *committed_rev, pool));
+
+  /* Extract date and author from these revprops. */
+  committed_date_s = apr_hash_get(revprops,
+                                  SVN_PROP_REVISION_DATE,
+                                  sizeof(SVN_PROP_REVISION_DATE)-1);
+  last_author_s = apr_hash_get(revprops,
+                               SVN_PROP_REVISION_AUTHOR,
+                               sizeof(SVN_PROP_REVISION_AUTHOR)-1);
 
   *committed_date = committed_date_s ? committed_date_s->data : NULL;
   *last_author = last_author_s ? last_author_s->data : NULL;

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_subr/auth.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_subr/auth.c Tue Mar  6 17:50:23 2012
@@ -35,13 +35,20 @@
 #include "svn_dso.h"
 #include "svn_version.h"
 
-/* The good way to think of this machinery is as a set of tables.
+/* AN OVERVIEW
+   ===========
 
-   - Each type of credentials selects a single table.
+   A good way to think of this machinery is as a set of tables.
 
-   - In a given table, each row is a 'provider' capable of returning
-     the same type of credentials.  Each column represents a
-     provider's repeated attempts to provide credentials.
+     - Each type of credentials selects a single table.
+
+     - In a given table, each row is a 'provider' capable of returning
+       the same type of credentials.  Each column represents a
+       provider's repeated attempts to provide credentials.
+
+
+   Fetching Credentials from Providers
+   -----------------------------------
 
    When the caller asks for a particular type of credentials, the
    machinery in this file walks over the appropriate table.  It starts
@@ -55,6 +62,23 @@
 
    Note that the caller cannot see the table traversal, and thus has
    no idea when we switch providers.
+
+
+   Storing Credentials with Providers
+   ----------------------------------
+
+   When the server has validated a set of credentials, and when
+   credential caching is enabled, we have the chance to store those
+   credentials for later use.  The provider which provided the working
+   credentials is the first one given the opportunity to (re)cache
+   those credentials.  Its save_credentials() function is invoked with
+   the working credentials.  If that provider reports that it
+   successfully stored the credentials, we're done.  Otherwise, we
+   walk the providers (rows) for that type of credentials in order
+   from the top of the table, allowing each in turn the opportunity to
+   store the credentials.  When one reports that it has done so
+   successfully -- or when we run out of providers (rows) to try --
+   the table walk ends.
 */
 
 

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_subr/cache-inprocess.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_subr/cache-inprocess.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_subr/cache-inprocess.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_subr/cache-inprocess.c Tue Mar  6 17:50:23 2012
@@ -201,7 +201,7 @@ inprocess_cache_get_internal(char **buff
 
       *size = entry->size;
     }
-    
+
   return SVN_NO_ERROR;
 }
 
@@ -213,16 +213,17 @@ inprocess_cache_get(void **value_p,
                     apr_pool_t *result_pool)
 {
   inprocess_cache_t *cache = cache_void;
-  char* buffer;
+  char* buffer = NULL;
   apr_size_t size;
 
-  SVN_MUTEX__WITH_LOCK(cache->mutex,
-                       inprocess_cache_get_internal(&buffer,
-                                                    &size,
-                                                    cache,
-                                                    key,
-                                                    result_pool));
-    
+  if (key)
+    SVN_MUTEX__WITH_LOCK(cache->mutex,
+                         inprocess_cache_get_internal(&buffer,
+                                                      &size,
+                                                      cache,
+                                                      key,
+                                                      result_pool));
+
   /* deserialize the buffer content. Usually, this will directly
      modify the buffer content directly.
    */
@@ -400,11 +401,12 @@ inprocess_cache_set(void *cache_void,
 {
   inprocess_cache_t *cache = cache_void;
 
-  SVN_MUTEX__WITH_LOCK(cache->mutex,
-                       inprocess_cache_set_internal(cache,
-                                                    key,
-                                                    value,
-                                                    scratch_pool));
+  if (key)
+    SVN_MUTEX__WITH_LOCK(cache->mutex,
+                         inprocess_cache_set_internal(cache,
+                                                      key,
+                                                      value,
+                                                      scratch_pool));
 
   return SVN_NO_ERROR;
 }
@@ -443,7 +445,7 @@ inprocess_cache_iter(svn_boolean_t *comp
   b.user_baton = user_baton;
 
   SVN_MUTEX__WITH_LOCK(cache->mutex,
-                       svn_iter_apr_hash(completed, cache->hash, 
+                       svn_iter_apr_hash(completed, cache->hash,
                                          iter_cb, &b, scratch_pool));
 
   return SVN_NO_ERROR;
@@ -482,14 +484,17 @@ inprocess_cache_get_partial(void **value
 {
   inprocess_cache_t *cache = cache_void;
 
-  SVN_MUTEX__WITH_LOCK(cache->mutex,
-                       inprocess_cache_get_partial_internal(value_p,
-                                                            found,
-                                                            cache,
-                                                            key,
-                                                            func,
-                                                            baton,
-                                                            result_pool));
+  if (key)
+    SVN_MUTEX__WITH_LOCK(cache->mutex,
+                         inprocess_cache_get_partial_internal(value_p,
+                                                              found,
+                                                              cache,
+                                                              key,
+                                                              func,
+                                                              baton,
+                                                              result_pool));
+  else
+    *found = FALSE;
 
   return SVN_NO_ERROR;
 }
@@ -526,12 +531,13 @@ inprocess_cache_set_partial(void *cache_
 {
   inprocess_cache_t *cache = cache_void;
 
-  SVN_MUTEX__WITH_LOCK(cache->mutex,
-                       inprocess_cache_set_partial_internal(cache,
-                                                            key,
-                                                            func,
-                                                            baton,
-                                                            scratch_pool));
+  if (key)
+    SVN_MUTEX__WITH_LOCK(cache->mutex,
+                         inprocess_cache_set_partial_internal(cache,
+                                                              key,
+                                                              func,
+                                                              baton,
+                                                              scratch_pool));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/reintegrate-keep-alive/subversion/libsvn_subr/cache-membuffer.c
URL: http://svn.apache.org/viewvc/subversion/branches/reintegrate-keep-alive/subversion/libsvn_subr/cache-membuffer.c?rev=1297604&r1=1297603&r2=1297604&view=diff
==============================================================================
--- subversion/branches/reintegrate-keep-alive/subversion/libsvn_subr/cache-membuffer.c (original)
+++ subversion/branches/reintegrate-keep-alive/subversion/libsvn_subr/cache-membuffer.c Tue Mar  6 17:50:23 2012
@@ -136,6 +136,13 @@
  */
 #define NO_OFFSET APR_UINT64_MAX
 
+/* To save space in our group structure, we only use 32 bit size values
+ * and, therefore, limit the size of each entry to just below 4GB.
+ * Supporting larger items is not a good idea as the data transfer
+ * to and from the cache would block other threads for a very long time.
+ */
+#define MAX_ITEM_SIZE ((apr_uint32_t)(0 - ITEM_ALIGNMENT))
+
 /* Debugging / corruption detection support.
  * If you define this macro, the getter functions will performed expensive
  * checks on the item data, requested keys and entry types. If there is
@@ -395,6 +402,11 @@ struct svn_membuffer_t
    */
   apr_uint64_t data_used;
 
+  /* Largest entry size that we would accept.  For total cache sizes
+   * less than 4TB (sic!), this is determined by the total cache size.
+   */
+  apr_uint64_t max_entry_size;
+
 
   /* Number of used dictionary entries, i.e. number of cached items.
    * In conjunction with hit_count, this is used calculate the average
@@ -589,6 +601,9 @@ get_group_index(svn_membuffer_t **cache,
   svn_checksum_t *checksum;
   svn_error_t *err;
 
+  if (key == NULL)
+    return NO_INDEX;
+
   err = svn_checksum(&checksum, svn_checksum_md5, key, len, pool);
   if (err != NULL)
   {
@@ -946,6 +961,7 @@ svn_cache__membuffer_cache_create(svn_me
   apr_uint32_t group_count;
   apr_uint32_t group_init_size;
   apr_uint64_t data_size;
+  apr_uint64_t max_entry_size;
 
   /* Determine a reasonable number of cache segments. Segmentation is
    * only useful for multi-threaded / multi-core servers as it reduces
@@ -989,8 +1005,19 @@ svn_cache__membuffer_cache_create(svn_me
    */
   data_size = total_size - directory_size;
 
+  /* For cache sizes > 4TB, individual cache segments will be larger
+   * than 16GB allowing for >4GB entries.  But caching chunks larger
+   * than 4GB is simply not supported.
+   */
+  max_entry_size = data_size / 4 > MAX_ITEM_SIZE
+                 ? MAX_ITEM_SIZE
+                 : data_size / 4;
+  
   /* to keep the entries small, we use 32 bit indices only
-   * -> we need to ensure that no more then 4G entries exist
+   * -> we need to ensure that no more then 4G entries exist.
+   * 
+   * Note, that this limit could only be exceeded in a very
+   * theoretical setup with about 1EB of cache.
    */
   group_count = directory_size / sizeof(entry_group_t);
   if (group_count >= (APR_UINT32_MAX / GROUP_SIZE))
@@ -1021,6 +1048,7 @@ svn_cache__membuffer_cache_create(svn_me
       c[seg].data = secure_aligned_alloc(pool, (apr_size_t)data_size, FALSE);
       c[seg].current_data = 0;
       c[seg].data_used = 0;
+      c[seg].max_entry_size = max_entry_size;
 
       c[seg].used_entries = 0;
       c[seg].hit_count = 0;
@@ -1052,14 +1080,14 @@ svn_cache__membuffer_cache_create(svn_me
 
 
 /* Try to insert the serialized item given in BUFFER with SIZE into
- * the group GROUP_INDEX of CACHE and uniquely identify it by hash 
- * value TO_FIND. 
- * 
+ * the group GROUP_INDEX of CACHE and uniquely identify it by hash
+ * value TO_FIND.
+ *
  * However, there is no guarantee that it will actually be put into
  * the cache. If there is already some data associated with TO_FIND,
  * it will be removed from the cache even if the new data cannot
  * be inserted.
- * 
+ *
  * Note: This function requires the caller to serialization access.
  * Don't call it directly, call membuffer_cache_get_partial instead.
  */
@@ -1075,7 +1103,7 @@ membuffer_cache_set_internal(svn_membuff
   /* if necessary, enlarge the insertion window.
    */
   if (   buffer != NULL
-      && cache->data_size / 4 > size
+      && cache->max_entry_size >= size
       && ensure_data_insertable(cache, size))
     {
       /* Remove old data for this key, if that exists.
@@ -1162,11 +1190,11 @@ membuffer_cache_set(svn_membuffer_t *cac
 }
 
 /* Look for the cache entry in group GROUP_INDEX of CACHE, identified
- * by the hash value TO_FIND. If no item has been stored for KEY, 
+ * by the hash value TO_FIND. If no item has been stored for KEY,
  * *BUFFER will be NULL. Otherwise, return a copy of the serialized
- * data in *BUFFER and return its size in *ITEM_SIZE. Allocations will 
+ * data in *BUFFER and return its size in *ITEM_SIZE. Allocations will
  * be done in POOL.
- * 
+ *
  * Note: This function requires the caller to serialization access.
  * Don't call it directly, call membuffer_cache_get_partial instead.
  */
@@ -1192,10 +1220,10 @@ membuffer_cache_get_internal(svn_membuff
        */
       *buffer = NULL;
       *item_size = 0;
-  
+
       return SVN_NO_ERROR;
     }
-    
+
   size = ALIGN_VALUE(entry->size);
   *buffer = ALIGN_POINTER(apr_palloc(result_pool, size + ITEM_ALIGNMENT-1));
   memcpy(*buffer, (const char*)cache->data + entry->offset, size);
@@ -1222,7 +1250,7 @@ membuffer_cache_get_internal(svn_membuff
   cache->total_hits++;
 
   *item_size = entry->size;
-  
+
   return SVN_NO_ERROR;
 }
 
@@ -1272,18 +1300,18 @@ membuffer_cache_get(svn_membuffer_t *cac
       *item = NULL;
       return SVN_NO_ERROR;
     }
-    
+
   return deserializer(item, buffer, size, result_pool);
 }
 
 /* Look for the cache entry in group GROUP_INDEX of CACHE, identified
  * by the hash value TO_FIND. FOUND indicates whether that entry exists.
  * If not found, *ITEM will be NULL.
- * 
- * Otherwise, the DESERIALIZER is called with that entry and the BATON 
+ *
+ * Otherwise, the DESERIALIZER is called with that entry and the BATON
  * provided and will extract the desired information. The result is set
  * in *ITEM. Allocations will be done in POOL.
- * 
+ *
  * Note: This function requires the caller to serialization access.
  * Don't call it directly, call membuffer_cache_get_partial instead.
  */
@@ -1304,7 +1332,7 @@ membuffer_cache_get_partial_internal(svn
     {
       *item = NULL;
       *found = FALSE;
-      
+
       return SVN_NO_ERROR;
     }
   else
@@ -1363,11 +1391,12 @@ membuffer_cache_get_partial(svn_membuffe
 
   group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
 
-  SVN_MUTEX__WITH_LOCK(cache->mutex,
-                       membuffer_cache_get_partial_internal
-                           (cache, group_index, to_find, item, found,
-                            deserializer, baton, DEBUG_CACHE_MEMBUFFER_TAG
-                            result_pool));
+  if (group_index != NO_INDEX)
+    SVN_MUTEX__WITH_LOCK(cache->mutex,
+                         membuffer_cache_get_partial_internal
+                             (cache, group_index, to_find, item, found,
+                              deserializer, baton, DEBUG_CACHE_MEMBUFFER_TAG
+                              result_pool));
 
   return SVN_NO_ERROR;
 }
@@ -1375,10 +1404,10 @@ membuffer_cache_get_partial(svn_membuffe
 /* Look for the cache entry in group GROUP_INDEX of CACHE, identified
  * by the hash value TO_FIND. If no entry has been found, the function
  * returns without modifying the cache.
- * 
+ *
  * Otherwise, FUNC is called with that entry and the BATON provided
  * and may modify the cache entry. Allocations will be done in POOL.
- * 
+ *
  * Note: This function requires the caller to serialization access.
  * Don't call it directly, call membuffer_cache_set_partial instead.
  */
@@ -1448,7 +1477,7 @@ membuffer_cache_set_partial_internal(svn
               /* Remove the old entry and try to make space for the new one.
                */
               drop_entry(cache, entry);
-              if (   (cache->data_size / 4 > size)
+              if (   (cache->max_entry_size >= size)
                   && ensure_data_insertable(cache, size))
                 {
                   /* Write the new entry.
@@ -1499,11 +1528,12 @@ membuffer_cache_set_partial(svn_membuffe
    */
   group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
 
-  SVN_MUTEX__WITH_LOCK(cache->mutex,
-                       membuffer_cache_set_partial_internal
-                           (cache, group_index, to_find, func, baton,
-                            DEBUG_CACHE_MEMBUFFER_TAG_ARG
-                            scratch_pool));
+  if (group_index != NO_INDEX)
+    SVN_MUTEX__WITH_LOCK(cache->mutex,
+                         membuffer_cache_set_partial_internal
+                             (cache, group_index, to_find, func, baton,
+                              DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                              scratch_pool));
 
   /* done here -> unlock the cache
    */
@@ -1597,14 +1627,22 @@ combine_key(const void *prefix,
             apr_size_t *full_key_len,
             apr_pool_t *pool)
 {
-  if (key_len == APR_HASH_KEY_STRING)
-    key_len = strlen((const char *) key);
+  if (key == NULL)
+    {
+      *full_key = NULL;
+      *full_key_len = 0;
+    }
+  else
+    {
+      if (key_len == APR_HASH_KEY_STRING)
+        key_len = strlen((const char *) key);
 
-  *full_key_len = prefix_len + key_len;
-  *full_key = apr_palloc(pool, *full_key_len);
+      *full_key_len = prefix_len + key_len;
+      *full_key = apr_palloc(pool, *full_key_len);
 
-  memcpy(*full_key, prefix, prefix_len);
-  memcpy((char *)*full_key + prefix_len, key, key_len);
+      memcpy(*full_key, prefix, prefix_len);
+      memcpy((char *)*full_key + prefix_len, key, key_len);
+    }
 }
 
 /* Implement svn_cache__vtable_t.get (not thread-safe)
@@ -1810,8 +1848,7 @@ svn_membuffer_cache_is_cachable(void *ca
    * must be small enough to be stored in a 32 bit value.
    */
   svn_membuffer_cache_t *cache = cache_void;
-  return (size < cache->membuffer->data_size / 4)
-      && (size < APR_UINT32_MAX - ITEM_ALIGNMENT);
+  return size <= cache->membuffer->max_entry_size;
 }
 
 /* Add statistics of SEGMENT to INFO.
@@ -1859,7 +1896,7 @@ svn_membuffer_cache_get_info(void *cache
   for (i = 0; i < cache->membuffer->segment_count; ++i)
     {
       svn_membuffer_t *segment = cache->membuffer + i;
-      SVN_MUTEX__WITH_LOCK(segment->mutex, 
+      SVN_MUTEX__WITH_LOCK(segment->mutex,
                            svn_membuffer_get_segment_info(segment, info));
     }
 
@@ -1889,13 +1926,13 @@ svn_membuffer_cache_get_synced(void **va
                                apr_pool_t *result_pool)
 {
   svn_membuffer_cache_t *cache = cache_void;
-  SVN_MUTEX__WITH_LOCK(cache->mutex, 
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
                        svn_membuffer_cache_get(value_p,
                                                found,
                                                cache_void,
                                                key,
                                                result_pool));
-  
+
   return SVN_NO_ERROR;
 }
 
@@ -1908,12 +1945,12 @@ svn_membuffer_cache_set_synced(void *cac
                                apr_pool_t *scratch_pool)
 {
   svn_membuffer_cache_t *cache = cache_void;
-  SVN_MUTEX__WITH_LOCK(cache->mutex, 
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
                        svn_membuffer_cache_set(cache_void,
                                                key,
                                                value,
                                                scratch_pool));
-  
+
   return SVN_NO_ERROR;
 }
 
@@ -1929,7 +1966,7 @@ svn_membuffer_cache_get_partial_synced(v
                                        apr_pool_t *result_pool)
 {
   svn_membuffer_cache_t *cache = cache_void;
-  SVN_MUTEX__WITH_LOCK(cache->mutex, 
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
                        svn_membuffer_cache_get_partial(value_p,
                                                        found,
                                                        cache_void,
@@ -1937,7 +1974,7 @@ svn_membuffer_cache_get_partial_synced(v
                                                        func,
                                                        baton,
                                                        result_pool));
-  
+
   return SVN_NO_ERROR;
 }
 
@@ -1951,13 +1988,13 @@ svn_membuffer_cache_set_partial_synced(v
                                        apr_pool_t *scratch_pool)
 {
   svn_membuffer_cache_t *cache = cache_void;
-  SVN_MUTEX__WITH_LOCK(cache->mutex, 
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
                        svn_membuffer_cache_set_partial(cache_void,
                                                        key,
                                                        func,
                                                        baton,
                                                        scratch_pool));
-  
+
   return SVN_NO_ERROR;
 }
 
@@ -1999,8 +2036,10 @@ deserialize_svn_stringbuf(void **item,
                           apr_size_t buffer_size,
                           apr_pool_t *result_pool)
 {
-  svn_string_t *value_str = apr_palloc(result_pool, sizeof(svn_string_t));
+  svn_stringbuf_t *value_str = apr_palloc(result_pool, sizeof(svn_stringbuf_t));
 
+  value_str->pool = result_pool;
+  value_str->blocksize = buffer_size;
   value_str->data = buffer;
   value_str->len = buffer_size-1;
   *item = value_str;
@@ -2042,7 +2081,7 @@ svn_cache__create_membuffer_cache(svn_ca
   cache->alloc_counter = 0;
 
   SVN_ERR(svn_mutex__init(&cache->mutex, thread_safe, pool));
-  
+
   /* for performance reasons, we don't actually store the full prefix but a
    * hash value of it
    */
@@ -2063,7 +2102,7 @@ svn_cache__create_membuffer_cache(svn_ca
 
   /* initialize the generic cache wrapper
    */
-  wrapper->vtable = thread_safe ? &membuffer_cache_synced_vtable 
+  wrapper->vtable = thread_safe ? &membuffer_cache_synced_vtable
                                 : &membuffer_cache_vtable;
   wrapper->cache_internal = cache;
   wrapper->error_handler = 0;